Download - Hierarquia de Memória
![Page 1: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/1.jpg)
Hierarquia de Memória
Bruno C. Bourbon
Jarbas J. de O. Júnior
{bcb, jjoj} @ cin.ufpe.br
![Page 2: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/2.jpg)
Roteiro
Motivação Introdução Organização da Cache Alinhamento do bloco da Cache Prefetching (pré-busca) Intercâmbio de laços Bloqueamento (Blocking) Garbage Collection e hierarquia de memória Conclusões Referências
![Page 3: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/3.jpg)
Motivação
No últimos vinte anos:– Velocidade da CPU aumentou 60% / ano– Velocidade da Memória apenas 10% / ano
A laguna pode ser preenchida com memória cache
A cache é sub-utilizada– Aproveitamento mínimo das grandes caches
Uso ineficiente = baixa performace– Como aumentar o uso? Conscientização da cache
![Page 4: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/4.jpg)
Mais Motivos
Paralelismo da instruções:– Instruções SIMD consomem dados de 2 a 8 vezes mais que
uma instrução normal Lei de Probesting:
– “Melhorias das tecnologias de compiladores dobra o desempenho dos computadores a cada 18 anos.”
– Corolário: “Não espere que o compilador faça o serviço por você.”
Lei de Moore:– Consoles não a acompanham
• Hardware fixo• Títulos de 2ª e 3ª gerações tem que melhor de alguma maneira
![Page 5: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/5.jpg)
Introdução
Precisamos lembrar a arquitetura de memória:
![Page 6: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/6.jpg)
Organização da Cache
Princípio da Localidade– Localidade Temporal:
• Num futuro próximo, o programa irá referenciar as instruções e dados referenciados recentemente.
– Localidade Espacial: • Num futuro próximo, o programa irá referenciar
as instruções e dados que tenham endereços próximos das últimas referências.
![Page 7: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/7.jpg)
Organização da Cache
Mapeamento– Direto– Completamente Associativo– Associativo por conjunto
Leitura– Busca em demanda (Fetch On Demand ou Fetch)– Pré-Busca (Prefetch)
Escrita– Write-Through– Write-Back
![Page 8: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/8.jpg)
Mapeamento Direto
Cada bloco na memória principal é mapeado em uma única linha do cache– Módulo o número de blocos
Endereço é dividido em duas partes:– w bits menos significativos identificam um byte na
linha– s bits mais significativos identificam um bloco
Os s bits são divididos em um campo que identifica a linha com r bits e em uma Tag de s-r bits
![Page 9: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/9.jpg)
Mapeamento Direto
![Page 10: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/10.jpg)
Mapeamento Completamente Associativo
Qualquer bloco da memória pode ser levado para qualquer linha do cache
O endereço é dividido em uma Tag que identifica a linha e no identificador do byte
![Page 11: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/11.jpg)
Mapeamento Completamente Associativo
![Page 12: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/12.jpg)
Mapeamento Associativo por Conjunto
A cache é dividida em um número de conjuntos (set) Cada conjunto tem um certo número de linha (define
a associatividade) Um dado bloco da memória pode ser carregado em
qualquer linha de um único conjunto na cache– Módulo número de sets
![Page 13: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/13.jpg)
Mapeamento Associativo por Conjunto
![Page 14: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/14.jpg)
Leitura da Cache (Busca)
Estratégias para busca de palavras ou linhas da memória principal– busca por demanda (fetch)– Pré-busca (prefetch)
Fetch por demanda– Fetch da linha quando ocorre miss– Estratégia mais simples, não exige hardware adicional
Prefetch– Fetch da linha antes que ela seja necessária– p.ex: Prefetch da linha i+1 quando a linha i é inicialmente
referenciada
![Page 15: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/15.jpg)
Escrita na Cache
Leitura na cache: não há discrepância entre cache e memória principal
Escrita na cache: cópias da palavra na cache e na memória principal podem ter valores diferentes
Valores deveriam ficar iguais em razão de: – Acessos de E/S feitos através da memória principal – Acessos à memória principal por múltiplos processadores
Tempo médio de acesso à cache é aumentado pela necessidade de atualizações da memória principal
Mecanismos de coerência de escrita– write-through – write-back
![Page 16: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/16.jpg)
Alinhamento de Blocos da Cache
Blocos de Cache tem tipicamente o tamanho de um objeto.– Esperamos que um algoritmo que utilize um
campo de um objeto utilize outros campos do mesmo.
Se x ocupa um Múltiplo do limite de B, então ele ocupa dois diferentes blocos da cache.
Se x não ultrapassa o limite um múltiplo de B, então os campos serão acessados em apenas um bloco de cache.
![Page 17: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/17.jpg)
Alinhamento de Blocos da Cache
Alocar objetos seqüencialmente:– Se o próximo objeto não cabe na porção restante
do bloco atual, pule para o começo do próximo bloco.
Aloque os objetos de tamanhos T num área de memória, todos alinhados com limite de multiplicidade T (em relação ao tamanho do bloco). – Elimina o cruzamento de blocos (block-crossing),
sem desperdiçar espaço entre objetos de tamanho comum.
![Page 18: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/18.jpg)
Alinhamento de Blocos da Cache
Desperdício de espaço:– Espaço vazio no final de cada bloco
Ganho de velocidade:– Se um conjunto S de objetos é frequentemente acessado, o
alinhamento pode reduzir o espaço ocupado por S. Ajustando ao um espaço que caiba ele.
Alinhamento pode ser aplicado tanto a dados globais e estáticos como dinâmicos(heap).– Para dados globais e estáticos utiliza-se as diretivas de
alocação da linguagem assembler.– Para variáveis dinâmicas(heap) o alocador de memória
deverá cuidar disso em tempo de execução.
![Page 19: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/19.jpg)
Alinhamento de Instruções
Instruções ocupa cache assim como dados:– Alinhamento e block-crossing são
aplicavéis Alinhe o inicio de conjuntos de
instruções mais usadas no limite de um “múltiplo de B”– Instruções poucos usadas não deve se
alinhadas com as mais utilizadas
![Page 20: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/20.jpg)
Prefetching
Um miss na cache custa vários ciclos.– Se for na cache secundária custa ainda
mais. Em alguns casos pode ser previsto a
utilização do dado. O compilador pode utilizar uma
instrução de prefetch para antecipar o carregamento de um dado (ou vários).
![Page 21: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/21.jpg)
Prefetching
Se prefetching falhar não afetará a corretude do programa.
Muitas processadores possuem algum tipo de instrução de prefetch
A utilização de reordenação por levar ao efeito de prefetch.
![Page 22: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/22.jpg)
Instruções de Prefetch
Algumas processadores na possuem instruções de prefetch, mas possuem instruções de load que não bloqueiam.
Ou seja utilizar um load para levar um dado para cache, mesmo que não seja utilizado naquele momento.
A dica: carrega os dados somente quando múltiplos do tamanho de um bloco
![Page 23: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/23.jpg)
Prefetch para armazenamento
Às vezes podemos prever, em tempo de compilação, quando haverá uma falta de cache (cache miss) em uma instrução .
for i <- to N – 1 A[i] <- i------------------------------------------for i <- 0 to N – 1 if i mod blocksize = 0 then prefetch A[i + K] A[i] <- i
![Page 24: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/24.jpg)
Prefetch (resumo)
É aplicável quando:– A máquina possui uma instrução de
prefetch;– A máquina não reordena as instruções
dinamicamente;– O dado em questão é maior que a cache,
ou não se espera que esteja na cache.
![Page 25: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/25.jpg)
Intercâmbio de Laços
Considere o seguinte laço:
for i <- 0 to N – 1
for j <- 0 to M – 1
for k <- 0 to P – 1
A[i,j,k] <- (B[i,j-1,k]+B[i,j,k]+B[i,j+1,k])
O valor B[i,j+1,k] é reusado na próxima iteração do laço do j (no qual seu “nome” é B[i,j,k])
![Page 26: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/26.jpg)
Intercâmbio de Laços
j0 j1 j2 j3 ...
k0
k1
k2
k3
...
k = 0j = 1i = 0
k = 1j = 1i = 0
k = 2j = 1i = 0
for i <- 0 to N – 1
for j <- 0 to M – 1
for k <- 0 to P – 1
A[i,j,k] <- (B[i,j-1,k]+B[i,j,k]+B[i,j+1,k])
k = 0j = 2i = 0
Falta!
![Page 27: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/27.jpg)
Intercâmbio de Laços
j0 j1 j2 j3 ...
k0
k1
k2
k3
...
k = 0j = 1i = 0
for i <- 0 to N – 1
for k <- 0 to P – 1
for j <- 0 to M – 1
A[i,j,k] <- (B[i,j-1,k]+B[i,j,k]+B[i,j+1,k])
k = 0j = 2i = 0
k = 0j = 3i = 0
Trocando-seos laços...
![Page 28: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/28.jpg)
Intercâmbio de LaçosMAS ATENÇÃO!
Para que um intercâmbio de laços seja válido,não pode haver dependência de dados entre as iterações.
É necessário examinar o grafo de dependência de dados do cálculo:– Dizemos que a iteração (j,k) depende da (j’,k’) se:
• (j’,k’) calcular valores que são usados por (j,k) (leitura-depois-de-escrita)
• (j’,k’) armazena valores que são sobre-escritos por (j,k) (escrita-depois-de-escrita)
• Ou (j’,k’) lê valores que são sobre-escritos por (j,k) (escrita-depois-de-leitura)
![Page 29: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/29.jpg)
Bloqueamento
Caso geral Substituição Escalar Bloqueamento em todos os níveis da
hierarquia de memória Desenrolando “as parada” (Unroll and
Jam)
![Page 30: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/30.jpg)
Bloqueamento
Considere o seguinte laço para multiplicação de matrizes, C=A.Bfor i <- 0 to N – 1 for j <- 0 to N – 1 for k <- 0 to N – 1 C[i,j] <- C[i,j] + A[i,k].B[k,j]
Supondo que apenas as matrizes A e B e nada mais coubesse simultaneamente na memória cache, o laço k roda sem faltas, havendo somente uma falta para C[i,j] em cada iteração do laço j.
![Page 31: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/31.jpg)
Bloqueamento
for i <- 0 to N – 1 for j <- 0 to N – 1 for k <- 0 to N – 1 C[i,j] <- C[i,j] + A[i,k].B[k,j]
j0 j1 j2 j3 ...
i0
i1
i2
i3
...
j0 j1 j2 j3 ...
i0
i1
i2
i3
...
A B
MEM.CACHE
![Page 32: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/32.jpg)
Bloqueamento
E se a cache, for menor que o suficiente para armazenar as duas matrizes simultaneamente?
Mais exatamente: se a cache suportar no máximo 2.c.N elementos (pontos flutuantes), onde 1 < c < N?– Nesse caso, para as referências a B[k,j],
haverão sempre faltas.
![Page 33: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/33.jpg)
Bloqueamentofor i <- 0 to N – 1
for j <- 0 to N – 1
for k <- 0 to N – 1
C[i,j] <- C[i,j] + A[i,k].B[k,j]
j0 j1 j2 j3 ...
i0
i1
i2
i3
...
j0 j1 j2 j3 ...
0
1
2
3
...
A B
MEM.CACHE
Linha i0
Linha i0 de A
2.c
N
Coluna j0 de B
Coluna j1 de B
Coluna j2 de B
2.c < N !!! Então sempre ocorrerá falta de B[k,j] depois que a cache encher pela primeira vez
Coluna j(2c) de B
Linha i1
Linha i1 de A
Coluna j(2c+1) de B
Coluna j(2c+2) de B
Coluna j0 de B
![Page 34: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/34.jpg)
Bloqueamento
for i <- 0 to N – 1
for j <- 0 to N – 1
for k <- 0 to N – 1
C[i,j] <- C[i,j] + A[i,k].B[k,j]
Neste caso, o intercâmbio de laço não resolve, pois se o laço j ficar para fora, os elementos de A sofrerão faltas. E se o laço k ficar para fora, os elementos de C sofrerão faltas!
![Page 35: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/35.jpg)
Bloqueamento
O pulo da gato:– Reusar as linhas da matriz A e as colunas de B
enquanto ainda estão na cache.– Para isso podemos calcular o bloco c x c da
matriz C a partir de c linhas de A e c colunas de B. Já que nossa memória cache possui tamanho 2.c.N:
for i <- i0 to i0 + c - 1 for j <- j0 to j0 + c -1 for k <- 0 to N – 1 C[i,j] <- C[i,j] + A[i,k].B[k,j]
![Page 36: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/36.jpg)
Bloqueamentofor i <- i0 to i0 + c - 1 for j <- j0 to j0 + c -1 for k <- 0 to N – 1 C[i,j] <- C[i,j] + A[i,k].B[k,j]
j0 j1 j2 j3 ...
i0
i1
i2
i3
...
j0 j1 j2 j3 ...
0
1
2
3
...
A B
MEM.CACHE
Linha i0
Lin i0 A
N
2c
Col j0 B
Col j1 B
Col j2 B
Col j(2c) B
Linha i1
Lin i1 A
Linha i2
Lin i2 A
Linha i3
Lin i3 A
c c
![Page 37: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/37.jpg)
Bloqueamento
Agora só falta juntar os blocos:for i0 <- 0 to N – 1 by c
for j0 <- 0 to N – 1 by c
for i <- i0 to min(i0 + c – 1, N – 1)
for j <- j0 to min (j0 + c –1, N – 1)
for k <- 0 to N – 1
C[i,j] <- C[i,j] + A[i,k].B[k,j]
![Page 38: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/38.jpg)
Bloqueamento
Faltas:– As faltas agora são apenas para carregar na
cache as novas colunas e as novas linhas cada vez que se for calcular um novo bloco c x c.
– Para carregar as novas c linhas e c colunas ocorrem 2.c.N faltas. E para calcular um bloco c x c são necessárias c.c.N iterações.
– Por tanto, o total de faltas por iteração é:
2.c.N / c.c.N = 2/c
![Page 39: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/39.jpg)
Bloqueamento:Substituição escalar
Mesmo que o acesso a C[i,j] quase nunca provoque uma falta na cache, nós poderíamos ainda deixá-la um nível de memória acima: nos registradores.
for i <- i0 to i0 + c - 1
for j <- j0 to j0 + c –1
s <- C[i,j]
for k <- 0 to N – 1
s <- s + A[i,k].B[k,j]
C[i,j] <- s
![Page 40: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/40.jpg)
Bloqueamento:Em todos os níveis da hierarquia
Se quisermos usar d registradores de ponto flutuante, podemos reescrever o código do cálculo do bloco c x c como:
for i <- i0 to i0 + c – 1 for k0 <- 0 to N – 1 by d for k <- k0 to k0 + d – 1 T[k-k0] <- A[i,k] for j <- j0 to j0 + c –1 s <- C[i,k] for k <- k0 to k0 + d – 1 s <- s + T[k-k0].B[k,j] C[i,j] <- s
Preenchendo os registradores
![Page 41: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/41.jpg)
Bloqueamento:Desenrolando “as parada” (Unroll and Jam)
Porém, para usar bloqueamento no nível de registradores, precisamos “desenrolar” o laço pois os registradores não podem ser indexados por subscripts.
Assim, supondo d = 3 (3 registadores):
for i <- i0 to i0 + c – 1 for k0 <- 0 to N – 1 by 3 t0 <- A[i,k0]; t1 <- A[i,k0+1]; t2 <- A[i,k0+2] for j <- j0 to j0 + c –1 C[i,j] <- C[i,j] + t0.B[k0,j] + t1.B[k0+1,j] + t2.B[k0+2,j]
![Page 42: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/42.jpg)
Garbage Collection e Hierarquia de Memória Sistemas que usam Garbage Collection têm a fama
de não usar a memória de forma otimizada. Porém, pode ser organizado para gerenciar a
memória de uma melhor forma:– Gerações
• Usar cache secundária para guardar a geração mais jovem
– Alocação Seqüencial– Poucos conflitos– Prefetching para Alocação– Agrupando objetos relacionados.
• Busca em profundidade
• Busca em largura
![Page 43: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/43.jpg)
Conclusão
A otimização do uso da memória cache pode aumentar muito o desempenho de um programa;
As técnicas vistas são úteis tanto para projeto de compiladores como para desenvolvimento de software em geral;
Exemplo concreto da importância do estudo de compiladores por desenvolvedores.
![Page 44: Hierarquia de Memória](https://reader036.vdocument.in/reader036/viewer/2022070406/5681404c550346895dabbeba/html5/thumbnails/44.jpg)
Referências
1. APPEL, Andrew W., Modern compiler implementation in Java.
2. ERICSON, Christer, Memory Otimization, GDC 2003
3. SILVA, Ivan S., CASSILO, Leonardo. Organização e Arquitetura de Computadores I: Memória. DIMAP – UFRN.
4. BARROS, Edna N. S., Infra-Estrutura de Hardware: Memória e Hierarquia de Memória. CIn - UFPE