A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Bruno C. Bourbon Jarbas J. de O. Júnior {bcb, cin.ufpe.br

Apresentações semelhantes


Apresentação em tema: "Bruno C. Bourbon Jarbas J. de O. Júnior {bcb, cin.ufpe.br"— Transcrição da apresentação:

1 Bruno C. Bourbon Jarbas J. de O. Júnior {bcb, jjoj} @ cin.ufpe.br
Hierarquia de Memória Bruno C. Bourbon Jarbas J. de O. Júnior {bcb, cin.ufpe.br

2 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

3 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

4 Mais Motivos Paralelismo da instruções: Lei de Probesting:
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

5 Introdução Precisamos lembrar a arquitetura de memória:
P - Porque somente cache e não memória principal e o disco? R - Porque isso é dever do sistema operacional, os aplicativos consideram a memória com sendo continua e única. P - Mas isso significa que os aplicativos devem ignorar a cache! R – Não pois ele faz parte do hardware, assim como o pipeline.

6 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. Nesta parte devemos descrever os três tipos de organização de memória cache: Direto, Associativo e Associativo por Conjunto. Seus funcionamentos, vantagens e desvantagens. Politicas de escrita e leitura:

7 Organização da Cache Mapeamento Leitura Escrita Direto
Completamente Associativo Associativo por conjunto Leitura Busca em demanda (Fetch On Demand ou Fetch) Pré-Busca (Prefetch) Escrita Write-Through Write-Back Mapeamento • O mapeamento entre a memória principal e a cache identifica se o dado buscado está na cache – Exemplo • Cache de 64 Kbystes • Blocos na cache de 4 Bytes – Cache com 16K (2^14) linhas de 4 bytes • Memória de 16 Mbytes – 24 bits de endereço 2^24 = 16M

8 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

9 Mapeamento Direto

10 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

11 Mapeamento Completamente Associativo

12 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

13 Mapeamento Associativo por Conjunto

14 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

15 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

16 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. ALINHAMENTO DE BLOCOS DE 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 Multiplo do limite de B, então ele ocupa dois diferentes blocos da cache. Se x não ultrapassa o limite um multiplo de B, então os campos serão acessados em apenas um bloco de cache. 1. Alocar objetos sequenciamente: Se o proximo objeto não cabe na porção restante do bloco atual, pule para o começo do proximo bloco 2. Aloque os objetos de tamanhos T num area de memória, todos alinhandos com limite de multiplicade T (em relação ao tamanho do bloco). Diminuindo o cruzamento de blocos (block-crossing), diminuindo o desperdicio de espaço para objetos de tamanho comum Vantagem e desvantagens Desperdicio 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 estaticos como dinamicos(heap). Para dados globais e estaticos utiliza-se as diretivas de alocação da linguagem assembler. Para variaveis dinamicas(heap) o alocador de memória deverá cuidar disso em tempo de execução.

17 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. 1. Alocar objetos sequenciamente: Se o proximo objeto não cabe na porção restante do bloco atual, pule para o começo do proximo bloco 2. Aloque os objetos de tamanhos T num area de memória, todos alinhandos com limite de multiplicade T (em relação ao tamanho do bloco). Diminuindo o cruzamento de blocos (block-crossing), diminuindo o desperdicio de espaço para objetos de tamanho comum

18 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. Desperdicio 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 estaticos como dinamicos(heap). Para dados globais e estaticos utiliza-se as diretivas de alocação da linguagem assembler. Para variaveis dinamicas(heap) o alocador de memória deverá cuidar disso em tempo de execução.

19 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

20 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).

21 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.

22 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

23 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]

24 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.

25 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])

26 Intercâmbio de Laços 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 = 2 j = 1 i = 0 k = 1 j = 1 i = 0 k = 0 j = 1 i = 0 j0 j j2 j3 ... k = 0 j = 2 i = 0 Falta! k0 k1 k2 k3 ...

27 Intercâmbio de Laços 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]) Trocando-se os laços... j0 j j2 j3 ... k = 0 j = 1 i = 0 k = 0 j = 2 i = 0 k = 0 j = 3 i = 0 k0 k1 k2 k3 ...

28 Intercâmbio de Laços MAS 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)

29 Bloqueamento Caso geral Substituição Escalar
Bloqueamento em todos os níveis da hierarquia de memória Desenrolando “as parada” (Unroll and Jam)

30 Bloqueamento Considere o seguinte laço para multiplicação de matrizes, C=A.B 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] 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.

31 Bloqueamento A B 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 j j2 j3 ... j0 j j2 j3 ... i0 i0 i1 i1 i2 i2 i3 i3 MEM. CACHE ... ... A B

32 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.

33 Bloqueamento A B N Linha i0 Linha i0 de A Linha i1 Linha i1 de A
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] N Linha i0 Linha i0 de A Linha i1 Linha i1 de A Coluna j0 de B Coluna j(2c) de B Coluna j0 de B 1 j0 j j2 j3 ... j0 j j2 j3 ... Coluna j1 de B 2 Coluna j(2c+1) de B Coluna j(2c+2) de B Coluna j2 de B i0 3 i1 ... i2 i3 MEM. CACHE ... 2.c < N !!! Então sempre ocorrerá falta de B[k,j] depois que a cache encher pela primeira vez 2.c A B

34 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!

35 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]

36 Bloqueamento A B 2c 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] c c Linha i0 Lin i0 A Linha i1 Lin i1 A Linha i2 Lin i2 A Col j0 B 1 j0 j j2 j3 ... j0 j j2 j3 ... Linha i3 Lin i3 A Col j1 B 2 Col j2 B i0 3 i1 ... i2 i3 MEM. CACHE Col j(2c) B N ... A B

37 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]

38 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

39 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

40 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] s <- s + T[k-k0].B[k,j] C[i,j] <- s Preenchendo os registradores

41 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]

42 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

43 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.

44 Referências APPEL, Andrew W., Modern compiler implementation in Java.
ERICSON, Christer, Memory Otimization, GDC 2003 SILVA, Ivan S., CASSILO, Leonardo. Organização e Arquitetura de Computadores I: Memória. DIMAP – UFRN. BARROS, Edna N. S., Infra-Estrutura de Hardware: Memória e Hierarquia de Memória. CIn - UFPE


Carregar ppt "Bruno C. Bourbon Jarbas J. de O. Júnior {bcb, cin.ufpe.br"

Apresentações semelhantes


Anúncios Google