Como o cache pode ser tão rápido?

37

Aqui está uma captura de tela de uma referência de cache:

Resultados do benchmark AIDA64 Cache & Memory

No benchmark, a velocidade de leitura do cache L1 é de cerca de 186 GB / s, com a latência sendo de cerca de 3-4 ciclos de clock. Como essa velocidade é alcançada?

Considere a memória aqui: a velocidade máxima teórica é 665 MHz (frequência de memória) x 2 (taxa de dados dupla) x 64 bits (largura do barramento) que é de cerca de 10,6 GB / s, mais próxima do valor de referência de 9,6 GB / s .

Mas, com o cache L1, mesmo que pudéssemos ler a cada ciclo com o processador em sua frequência máxima (3 GHz), precisaríamos de 496 linhas de dados para obter uma taxa de transferência que parece irreal. Isso se aplica a outros caches também.

o que estou perdendo? Como calculamos a taxa de transferência de um cache a partir de seus parâmetros?

Cavaleiro
fonte
14
você considerou o quão pequeno é o cache L1,2,3 e igualmente onde ele está fisicamente? Dica, você não precisa se preocupar com um padrão de barramento, se você possui o chip inteiro
JonRB 17/17/17
2
Além disso: o benchmark sabe o suficiente sobre o que está fazendo para garantir que alguns dados testados não sejam mantidos diretamente dentro de um registro?
rackandboneman
7
@rackandboneman: O AIDA64 é um benchmark bem respeitado, não algo que alguém acabou de hackear em C e deixar o compilador otimizar algumas cargas! Eu diria que as peças de marca de micropigmentação são escritas em montagem, com versões SSE ou AVX.
Peter Cordes
11
@ Peter Cordes resposta satisfatória - a uma pergunta necessária.
rackandboneman
11
Apenas para colocar os pensamentos em perspectiva física: em 1,4 nanossegundos, a luz viaja cerca de um pé e meio. Isso significa que, se o cache estiver localizado no outro lado da placa-mãe, uma latência como essa pode quebrar a relatividade. Ou seja, um erro de medição .
Arthur

Respostas:

35

Esta CPU possui ...

2 núcleos Uma instrução de 32 KB e cache de primeiro nível (L1) de dados de 32 KB para cada núcleo

Como existem dois núcleos, podemos esperar que o benchmark execute dois threads em paralelo. No entanto, o site deles fornece poucas informações, mas se olharmos aqui , as CPUs com mais núcleos parecem fornecer taxas de transferência L1 correspondentemente mais altas. Então, acho que o que é exibido é uma taxa de transferência total com todos os núcleos trabalhando em paralelo. Portanto, para sua CPU, devemos dividir por dois para um núcleo e um cache:

Read   93 GB/s
Write  47 GB/s
Copy   90 GB/s

Agora, o fato de "copiar" é 2x mais rápido que "gravar" é altamente suspeito. Como ele pode copiar mais rápido do que pode escrever? Aposto que o que o benchmark exibe como "cópia" é a soma da taxa de transferência de leitura + gravação e, nesse caso, ele lê e escreve a 45 GB / s, mas exibe 90, porque é um benchmark, e quem diabos confia nos benchmarks? Então, vamos ignorar "copiar".

Read   93 GB/s => 30 bytes/clock
Write  47 GB/s => 15 bytes/clock

Agora, um registro de 128 bits tem 16 bytes, perto o suficiente, então parece que esse cache pode fazer duas leituras de 128 bits e uma gravação por relógio.

É exatamente isso que você deseja otimizar realmente essas instruções de processamento de números do SSE: duas leituras e uma gravação por ciclo.

Isso provavelmente seria implementado com muitas linhas de dados paralelas, que é a maneira usual de transportar muitos dados muito rapidamente dentro de um chip.

peufeu
fonte
4
Na página 55 do documento @ next-hack, o link indica "Internamente, os acessos são de até 16 bytes. [...] Duas operações de carregamento e uma operação de armazenamento podem ser tratadas a cada ciclo". Isso explica por que a leitura é duas vezes mais rápida - ele pode fazer duas leituras na mesma operação enquanto também faz uma gravação.
Tom Carpenter
2
Sim, está contando claramente a cópia BW = ler e escrever. Isso parece tão válido quanto a alternativa, pois é significativo que as leituras e gravações possam ser executadas em paralelo. Observe que os números do OP para L2 / L3 têm uma cópia não muito maior que gravação e menor para memória. O barramento de memória DDR3 não é full-duplex: as mesmas linhas de dados são necessárias para leitura e gravação. (Para obter mais informações sobre a largura de banda do x86 memcpy / memset com repositórios NT versus repositórios regulares, consulte stackoverflow.com/questions/43343231/… ).
Peter Cordes
6
Você está supondo que o IvyBridge pode fazer 2 leituras e 1 gravação no mesmo ciclo de clock. Você está certo, mas apenas sob circunstâncias muito limitadas. O IvB possui apenas 2 portas AGU; portanto, normalmente é limitado a 2 operações de memória por relógio, até uma das quais pode ser uma loja . Porém, as cargas / lojas do 256b AVX demoram 2 ciclos para serem executadas nas portas de carga / armazenamento, necessitando apenas da AGU no primeiro ciclo. Portanto, um uop de endereço de loja pode ser executado na porta 2/3 durante o segundo ciclo de uma carga de 256b sem custar nenhuma largura de banda de carga. (UOPs loja de dados executados na porta 4.) Fonte: agner.org/optimize microarch pdf
Peter Cordes
2
Uma família AMD Bulldozer ou CPU Ryzen forneceria o mesmo número de leitura = 2x de gravação, mas eles realmente são limitados a 2 operações de memória por relógio (até uma pode ser uma gravação) sem brechas. leitura / gravação / cópia não detecta a diferença, mas a Triad pode ( a[i] = b[i] + c[i]). BTW, Intel Haswell e mais tarde têm uma AGU de loja na porta 7 que pode lidar com modos de endereçamento simples (não indexados), para que eles possam executar 2 carregamentos + 1 armazenamento de armazenamento por relógio. (E o caminho de dados para o L1D é 256b, portanto, dobra a largura de banda do L1D.) Veja o artigo de David Kanter: realworldtech.com/haswell-cpu/5
Peter Cordes
11
@AliChen: O OP mencionou explicitamente a latência de uso de carga de 4 ciclos do IvyBridge logo após a largura de banda, antes de perguntar como pode ser tão rápido.
Pedro Cordes
27

A resposta da @ peufeu indica que essas são larguras de banda agregadas em todo o sistema. L1 e L2 são caches privados por núcleo na família Intel Sandybridge, portanto, os números são 2x o que um único núcleo pode fazer. Mas isso ainda nos deixa com uma largura de banda impressionantemente alta e baixa latência.

O cache L1D está embutido no núcleo da CPU e está muito acoplado às unidades de execução de carga (e ao buffer de armazenamento) . Da mesma forma, o cache L1I fica ao lado da parte de busca / decodificação de instruções do núcleo. (Na verdade, eu não olhei para uma planta baixa de silício Sandybridge, então isso pode não ser literalmente verdade. A parte de edição / renomeação do front-end provavelmente está mais próxima do cache de UOP decodificado "L0", que economiza energia e tem melhor largura de banda do que os decodificadores.)

Mas com o cache L1, mesmo que pudéssemos ler a cada ciclo ...

Por que parar aí? A Intel, desde Sandybridge, e a AMD, desde o K8, podem executar 2 cargas por ciclo. Caches de várias portas e TLBs são uma coisa.

A descrição da microarquitetura Sandybridge de David Kanter tem um belo diagrama (que também se aplica à sua CPU IvyBridge):

(O "planejador unificado" mantém ALU e uops de memória aguardando que suas entradas estejam prontas e / ou aguardando sua porta de execução. (Por exemplo, vmovdqa ymm0, [rdi]decodifica para um uop de carregamento que precisa aguardar rdise um anterior add rdi,32ainda não tiver sido executado, por A Intel agenda agendamentos para portas no momento da emissão / renomeação . Este diagrama mostra apenas as portas de execução para entradas de memória, mas as UU ALU não executadas também competem por ela. O estágio de edição / renomeação adiciona entradas para o ROB e o planejador Eles permanecem no ROB até a aposentadoria, mas no planejador somente até o envio para uma porta de execução (esta é a terminologia da Intel; outras pessoas usam o problema e o despacho de maneira diferente). A AMD usa planejadores separados para números inteiros / FP, mas os modos de endereçamento sempre usam registros inteiros

Diagrama de memória SnB de David Kanter

Como isso mostra, existem apenas duas portas AGU (unidades de geração de endereços, que assumem um modo de endereçamento [rdi + rdx*4 + 1024]e produzem um endereço linear). Pode executar 2 operações de memória por relógio (de 128b / 16 bytes cada), sendo que uma delas é uma loja.

Mas ele tem um truque na manga: o SnB / IvB executa 256b AVX carrega / armazena como um único uop que leva 2 ciclos em uma porta de carregamento / armazenamento, mas só precisa da AGU no primeiro ciclo. Isso permite que um uop de endereço de loja seja executado no AGU na porta 2/3 durante o segundo ciclo sem perder nenhuma taxa de transferência de carga. Portanto, com o AVX (que os processadores Intel Pentium / Celeron não suportam: /), o SnB / IvB pode (em teoria) suportar 2 cargas e 1 armazenamento por ciclo.

Sua CPU IvyBridge é o encolhimento da Sandybridge (com algumas melhorias microarquiteturais, como eliminação de mov , ERMSB (memcpy / memset) e pré-busca de hardware da próxima página). A geração seguinte (Haswell) dobrou a largura de banda L1D por relógio, ampliando os caminhos de dados das unidades de execução para L1 de 128b para 256b, para que as cargas do AVX 256b possam sustentar 2 por relógio. Ele também adicionou uma porta AGU de armazenamento extra para modos de endereçamento simples.

A taxa de transferência de pico da Haswell / Skylake é de 96 bytes carregados + armazenados por relógio, mas o manual de otimização da Intel sugere que a taxa de transferência média sustentada da Skylake (ainda assumindo que não haja perdas de L1D ou TLB) é de ~ 81B por ciclo. (Um loop inteiro escalar pode suportar 2 cargas + 1 armazenamento por relógio, de acordo com meu teste no SKL, executando 7 uops (domínio não fundido) por relógio de 4 uops de domínio fundido. Mas diminui um pouco com operandos de 64 bits em vez de 32 bits, aparentemente, há algum limite de recursos microarquiteturais e não se trata apenas de agendar Uops de endereço de loja para a porta 2/3 e roubar ciclos de cargas.)

Como calculamos a taxa de transferência de um cache a partir de seus parâmetros?

Você não pode, a menos que os parâmetros incluam números de rendimento práticos. Como observado acima, mesmo o L1D da Skylake não consegue acompanhar suas unidades de execução de carregamento / armazenamento para vetores 256b. Embora seja próximo, e pode ser para números inteiros de 32 bits. (Não faria sentido ter mais unidades de carga do que o cache tinha portas de leitura ou vice-versa. Você deixaria de fora o hardware que nunca poderia ser totalmente utilizado. Observe que o L1D pode ter portas extras para enviar / receber linhas para / de outros núcleos, bem como para leituras / gravações de dentro do núcleo.)

Só de olhar para as larguras e relógios do barramento de dados, não dá toda a história. As larguras de banda L2 e L3 (e memória) podem ser limitadas pelo número de erros pendentes que L1 ou L2 podem rastrear . A largura de banda não pode exceder a latência * max_concurrency, e os chips com maior latência L3 (como um Xeon com muitos núcleos) têm muito menos largura de banda L3 com um único núcleo do que uma CPU dual / quad core da mesma microarquitetura. Consulte a seção "plataformas ligadas à latência" desta resposta do SO . As CPUs da família Sandybridge têm 10 buffers de preenchimento de linha para rastrear as falhas L1D (também usadas pelas lojas do NT).

(A largura de banda agregada de L3 / memória com muitos núcleos ativos é enorme em um grande Xeon, mas o código de thread único vê uma largura de banda pior do que em um quad core na mesma velocidade de clock, porque mais núcleos significam mais paradas no barramento em anel e, portanto, maior latência L3.)


Latência do cache

Como essa velocidade é alcançada?

A latência de uso de carga de 4 ciclos do cache L1D é bastante surpreendente , especialmente considerando que ele precisa começar com um modo de endereçamento [rsi + 32], portanto, é necessário adicionar um antes que ele tenha um endereço virtual . Em seguida, é necessário traduzir isso para físico para verificar as tags de cache para uma correspondência.

(Outros modos de endereçamento além de [base + 0-2047]dar um ciclo extra na família Intel Sandybridge, portanto, há um atalho nas AGUs para modos simples de endereçamento (típico para casos de busca de ponteiros em que baixa latência de uso de carga é provavelmente mais importante, mas também comum em geral) (Consulte o manual de otimização da Intel , seção Sandybridge 2.3.5.2 L1 DCache.) Isso também pressupõe nenhuma substituição de segmento e um endereço base de segmento 0, o que é normal.)

Ele também precisa investigar o buffer de armazenamento para verificar se ele se sobrepõe a outros armazenamentos anteriores. E isso deve ser resolvido mesmo que um uop de endereço de loja anterior (em ordem de programa) ainda não tenha sido executado, portanto, o endereço de loja não é conhecido. Mas, presumivelmente, isso pode acontecer em paralelo com a verificação de um acerto L1D. Se os dados L1D não forem necessários, porque o encaminhamento de loja pode fornecer os dados do buffer de armazenamento, isso não significa perda.

A Intel usa caches VIPT (virtualmente indexados fisicamente), como quase todo mundo, usando o truque padrão de ter o cache pequeno o suficiente e com associatividade alta o suficiente para se comportar como um cache PIPT (sem alias) com a velocidade do VIPT (pode indexar em paralelo com a pesquisa virtual-> física do TLB).

Os caches L1 da Intel são associativos de 32 kB e 8 vias. O tamanho da página é 4kiB. Isso significa que os bits de "índice" (que selecionam qual conjunto de 8 maneiras pode armazenar em cache qualquer linha) estão todos abaixo do deslocamento da página; ou seja, esses bits de endereço são deslocados em uma página e são sempre os mesmos no endereço virtual e físico.

Para obter mais detalhes sobre isso e outros detalhes sobre por que caches pequenos / rápidos são úteis / possíveis (e funcionam bem quando combinados com caches maiores e mais lentos), veja minha resposta sobre por que o L1D é menor / mais rápido que o L2 .

Caches pequenos podem fazer coisas que seriam muito caras em caches maiores, como buscar as matrizes de dados de um conjunto ao mesmo tempo que buscar tags. Portanto, uma vez que um comparador encontre qual tag corresponde, ele precisa compactar uma das oito linhas de cache de 64 bytes que já foram buscadas na SRAM.

(Na verdade, não é tão simples assim: o Sandybridge / Ivybridge usa um cache L1D com banco, com oito bancos de blocos de 16 bytes. Você pode obter conflitos entre bancos de cache se dois acessos ao mesmo banco em diferentes linhas de cache tentarem executar no mesmo ciclo. (Existem 8 bancos, portanto, isso pode acontecer com endereços com um múltiplo de 128, ou seja, 2 linhas de cache.)

O IvyBridge também não possui penalidade pelo acesso não alinhado, desde que não ultrapasse o limite da linha de cache de 64B. Acho que descobre quais bancos buscar com base nos bits de endereço baixos e configura qualquer mudança necessária para obter os 1 a 16 bytes de dados corretos.

Em divisões de linha de cache, ainda é apenas um uop, mas faz vários acessos ao cache. A penalidade ainda é pequena, exceto em 4k-splits. O Skylake torna as divisões de até 4k razoavelmente baratas, com latência de cerca de 11 ciclos, o mesmo que uma divisão de linha de cache normal com um modo de endereçamento complexo. Porém, a taxa de transferência dividida em 4k é significativamente pior que a divisão não dividida.


Fontes :

Peter Cordes
fonte
11
Isso é muito claro, exaustivo e bem escrito! +1!
next-hack
8

Nas CPUs modernas, a memória cache fica ao lado da CPU na mesma matriz (chip) , é feita usando SRAM, que é muito, muito mais rápida que a DRAM usada para os módulos de RAM em um PC.

Por unidade de memória (um bit ou byte), a SRAM é muito mais cara que a DRAM. É por isso que a DRAM também é usada em um PC.

Mas como a SRAM é fabricada com a mesma tecnologia que a própria CPU, ela é tão rápida quanto a CPU. Além disso, há apenas barramentos internos (na CPU) para lidar; portanto, se precisar ser um barramento de 496 linhas de largura, provavelmente é.

Bimpelrekkie
fonte
Obrigado pelo seu interesse. Eu já vi em alguns livros afirmando que as velocidades de acesso ao registro são superiores a 300 GB / s; nesse caso, para um processador de 3 GHz, a taxa de transferência do registro é de 100 B / ciclo, o que não é possível, pois os registros geralmente têm 64/128 bits de largura, eles não podiam produzir tanto. É isso que me preocupa. O GB / sa é a maneira correta de expressar a taxa de transferência.
Knight
3
@Knight lembre-se de que o IvB (como qualquer processador de alto desempenho) executa várias instruções por ciclo, como 3 operações de ALU, 2 cargas e 1 armazenamento. A maioria delas pode receber 2 entradas (cargas pares, para endereçamento indexado) e a carga leva até 3. Isso significa 13 registros com 8 bytes cada, 104 bytes (pode ser que uma combinação épica não seja permitida, mas existe não é indicação de que seja o caso do IvB, embora não possa ser sustentado). Se você também considerar os registros vetoriais, esse número aumentará ainda mais.
Harold
@harold: related: Haswell e Skylake parecem ter limites nas leituras de registros por relógio, embora isso possa estar no front-end e não afete uma explosão de execução depois que algumas entradas estiverem prontas. Talvez seja algum outro limite microarquitetural, mas eu encontrei gargalos no código que deveriam ser capazes de sustentar mais operações por relógio. agner.org/optimize/blog/read.php?i=415#852 . Em Haswell, meu melhor cenário é ler ~ 6,5 registros inteiros por ciclo de clock (sustentado). Também consegui obter 7 uops sustentados por dispatche / execução de relógio no Skylake (as lojas são o endereço da loja + os dados da loja).
Peter Cordes
@ PeterCordes que deve ser o front-end, certo? IIRC que também foi o problema historicamente (PPro para Core2) e não sei ao certo como os números fracionários fazem sentido. Embora meus números foram um pouco fora de qualquer maneira
Harold
@harold: sim, tenho certeza de que é um gargalo de front-end de algum tipo, provavelmente renomeado. O gargalo de leitura de registro do P6 estava em registros "frios" que precisavam ser lidos do arquivo de registro permanente no ROB em questão. Os registros recentemente modificados ainda estavam no ROB, e não havia gargalo nisso. Não investiguei muito com regs cold vs. hot no HSW / SKL, pois, por algum motivo, não pensei em aumentar meu loop acima de 4 uops / idealmente 1c por iteração. oops. IDK quanto dif há entre encaminhamento vs. leituras PRF (que precisam acontecer no momento da execução, não emitir / renomear).
Peter Cordes
4

Os caches L1 são estruturas de memória bastante amplas. A arquitetura dos caches L1 nos processadores Intel pode ser encontrada neste manual (fornecido pelo next-hack). No entanto, a interpretação de alguns parâmetros está incorreta, o "tamanho da linha de cache" não é a "largura dos dados", é o tamanho do bloco serial de acesso a dados atômicos.

A Tabela 2-17 (seção 2.3.5.1) indica que, nas cargas (leituras), a largura de banda do cache é de 2x16 = 32 bytes por núcleo por CYCLE . Isso por si só fornece largura de banda teórica de 96 Gb / s em um núcleo de 3GHz. Não está claro o que o benchmark citado relata, parece que ele mede dois núcleos trabalhando em paralelo, por isso gera 192 Gbps para dois núcleos.

Ale..chenski
fonte
2

Atrasos no portão são o que? 10 picossegundos? O tempo de ciclo para operações inteiras em pipeline é de 333 picossegundos, com várias atividades de decodificação e barramento e captura de dados em flip-flop antes do início do próximo ciclo de clock.

Espero que a atividade mais lenta na leitura de um cache esteja aguardando que os datalines se afastem o suficiente (provavelmente estes são diferenciais: uma referência e uma cobrança real do bit de leitura) para que um comparador / trava possa ser cronometrado para implementar um ação de feedback para converter uma pequena tensão em um grande balanço de tensão no nível lógico trilho a trilho (cerca de 1 volt).

analogsystemsrf
fonte
11
Lembre-se de que a latência L1D de 4 ciclos inclui a geração de endereços (para modos simples de endereçamento [reg + 0-2047]), uma pesquisa TLB e uma comparação de tags (associativa de 8 vias) e a colocação dos 16 bytes desalinhados resultantes no porta de saída da unidade de carga, para encaminhamento para outras unidades de execução. É latência 4c para um loop de perseguição de ponteiro mov rax, [rax].
22616 Peter Cordes