1 pontos por GN⁺ 2024-12-02 | 1 comentários | Compartilhar no WhatsApp
  • Em uma nova BIOS da ASRock B650 PG Lightning, o loop buffer do Zen 4 deixou de ser observado como fonte de micro-ops, e ao voltar para uma BIOS anterior ele é reativado
  • Essa estrutura parece ser um recurso para processar repetidamente pequenos loops no frontend e reduzir consumo de energia, com estimativa de 144 entradas em thread única e 72 entradas por thread com SMT de 2 threads
  • No SPEC CPU2017, a diferença de pontuação total entre loop buffer ativado e desativado fica em menos de 1%, então o impacto no desempenho geral parece muito pequeno
  • Com o loop buffer desligado, o Zen 4 passa a fornecer mais micro-ops pelo op cache, e como a largura de banda do op cache é suficiente em relação ao throughput do backend, isso dificilmente vira um gargalo de frontend
  • O motivo da desativação e o impacto real em consumo de energia são incertos, mas como a AMD quase não documentou nem divulgou esse recurso limitado, a maioria dos usuários e desenvolvedores dificilmente perceberá a mudança

Papel e limitações do loop buffer no Zen 4

  • O loop buffer é uma estrutura no frontend da CPU que guarda um pequeno conjunto de instruções já buscadas, permitindo desligar parte das etapas do frontend quando pequenos loops são executados repetidamente
    • Pode ajudar a reduzir consumo de energia
    • Também pode melhorar desempenho ao contornar limitações do frontend
    • É uma técnica usada há muito tempo em núcleos da Intel, Arm e AMD
  • O Zen 4 parece ser o único caso de um núcleo AMD de alto desempenho com loop buffer
  • O Processor Programming Reference do Zen 4 cita o loop buffer, junto com o op cache e os decodificadores, como fonte de dispatch de micro-ops
  • Pelos experimentos com contadores de desempenho, a capacidade é estimada da seguinte forma
    • 144 entradas em execução com thread única
    • 72 entradas por thread com SMT de 2 threads ativo, em divisão estática
  • Se houver CALL/RET dentro do loop, o loop buffer do Zen 4 não consegue capturar esse loop
  • O guia de otimização do Zen 4 da AMD não trata do loop buffer e apenas recomenda manter regiões de código quente dentro da capacidade do op cache

O loop buffer sumiu após uma atualização de BIOS

  • Após atualizar a ASRock B650 PG Lightning para a BIOS 3.10, o monitoramento de desempenho por hardware mostrou que o loop buffer não faz dispatch de micro-ops
  • Ao voltar para a BIOS 1.21, o loop buffer volta a ficar ativo
  • A desativação parece ter ocorrido entre o AGESA 1.0.0.6 da BIOS 1.21 e o AGESA 1.2.0.2a da BIOS 3.10
  • A AMD aplicou essa mudança sem anúncio ou divulgação específica
  • Em discussões paralelas com funcionários da AMD no Hot Chips 2024, o loop buffer foi descrito principalmente como um recurso de otimização de energia

Pequena diferença de desempenho no SPEC CPU2017

  • A pontuação total dos suites de inteiros e ponto flutuante do SPEC CPU2017 difere em menos de 1% entre loop buffer ativado e desativado
  • O ganho de desempenho com SMT também não é afetado pela desativação do loop buffer
  • O impacto pequeno acontece porque o op cache do Zen 4 já oferece mais largura de banda do que o estágio de rename/allocate do backend consegue consumir
  • Mesmo com o loop buffer ligado, os contadores de desempenho mostram que apenas uma pequena fração dos micro-ops vem dele
  • Também não foram observadas grandes perdas em benchmarks individuais
    • O 523.xalanbmk teve uma fração relevante do stream de instruções atendida pelo loop buffer, mas a pontuação ficou em 9,48 na BIOS nova e 9,44 na BIOS antiga, dentro da margem de erro
    • O 544.nab recebeu quase um quarto dos micro-ops pelo loop buffer, mas marcou 11,7 na BIOS nova com o loop buffer desligado, contra 11,5 antes, um aumento de 1,7%
    • Esse aumento pode ser apenas variação entre execuções
  • Nos contadores de desempenho da BIOS nova, o op cache assume o papel do loop buffer e atende uma parte maior do stream de instruções
  • Em 507.cactuBSSN, a cobertura do op cache cai um pouco e aparece um padrão em que os decodificadores fornecem cerca de um quarto de todos os micro-ops
    • Contadores de desempenho servem mais para mostrar tendências gerais do que medições 100% precisas
    • O dispatch do frontend é um evento especulativo, então também pode incluir instruções buscadas incorretamente após branches mal previstos

Possível economia de energia e atividade do frontend

  • O objetivo principal do loop buffer não é aumentar desempenho, e sim desligar oportunisticamente boa parte do frontend, incluindo o op cache
  • Os recursos de monitoramento de desempenho do Zen 4 incluem count mask, que permite contar ciclos em que um evento ultrapassa determinado limiar
    • Com o limiar em 1, é possível estimar em quantos ciclos cada fonte de micro-ops realmente forneceu micro-ops
    • Isso permite avaliar com que frequência o frontend pode ser desligado quando o loop buffer está ativo
  • No SPEC CPU2017, a frequência de ativação de cada fonte combina razoavelmente bem com a proporção de micro-ops entregue por ela
  • Em algumas cargas, há também muitos ciclos em que o frontend não fornece nada
    • 502.gcc e 520.omnetpp ficam bastante limitados pela latência de memória do backend
    • Se o mecanismo de execução fora de ordem não consegue manter instruções suficientes in flight para esconder a latência, o frontend não consegue mandar mais trabalho ao backend e fica ocioso
  • No suite de ponto flutuante, 544.nab e 508.namd usam o loop buffer durante uma parcela considerável dos ciclos do core
    • O 508.namd é uma carga de alto IPC com média de 3,64 IPC, então exige bastante throughput do frontend
    • Por ser favorável ao loop buffer, há oportunidade de desligar o op cache e economizar energia
  • Quando o loop buffer é desligado, o op cache precisa alimentar o core por mais ciclos
    • Em 523.xalanbmk, sem loop buffer o op cache precisa ficar ativo por mais 12% dos ciclos do core
    • 548.exchange2 é uma carga de alto IPC com média de 4,31 IPC, mas quase não usa o loop buffer mesmo quando ele está ligado, e o op cache fica ativo em mais de 85% dos ciclos do core
    • Em 508.namd, a taxa de atividade do op cache sobe de 56,67% com loop buffer ativo para 75,1% com ele desativado
  • Um loop buffer de 144 entradas é pequeno demais para cobrir grande parte do stream de instruções
    • Ele provavelmente só terá efeito perceptível quando o programa passa bastante tempo em pequenos loops e não está limitado pelo throughput ou pela latência do backend

Observações em Cyberpunk 2077

  • O benchmark embutido de Cyberpunk 2077 foi usado para verificar o impacto da desativação do loop buffer no desempenho em jogos
  • Para melhorar a consistência, o Core Performance Boost foi desativado em um Ryzen 9 7950X3D e todos os núcleos foram limitados a 4.2GHz
    • Foi definido o bit 25 do Hardware Configuration register MSR 0xC0010015
    • A RX 6900 XT foi limitada a 2GHz
    • As configurações do benchmark foram 1080p, preset médio, sem upscaling
  • Ao fixar o jogo no die com VCache, desativar o loop buffer quase não afetou o desempenho
  • Ao fixá-lo no die sem VCache, foi observada perda de 5% de desempenho com o loop buffer desativado, mas a causa não foi identificada
    • O benchmark foi reexecutado cerca de seis vezes
  • Em média, Cyberpunk 2077 teve cerca de 22% do stream de instruções atendido pelo loop buffer, tornando-se mais favorável a ele do que o esperado
    • Após a desativação, a participação do op cache no fornecimento de micro-ops subiu de 62% para 82%
  • O jogo não é uma carga de alto IPC, com média de 0,89 IPC com o loop buffer desativado e 1,02 IPC com ele ativo
    • A largura de banda do frontend não é uma grande preocupação
    • É possível que esteja limitado pelo backend ou por atrasos do branch predictor
  • Ao rodar no die com VCache, os contadores de desempenho mostraram média de 1,25 IPC com o loop buffer ativo e 1,07 IPC com ele desativado
    • Também foi observada uma pequena queda de desempenho na BIOS nova
    • É possível que o sistema tenha ficado mais próximo de um gargalo do lado da GPU em torno de 155 FPS

Incerteza nos resultados do contador de energia do core

  • Para verificar se a execução via loop buffer melhora a eficiência energética, também foi observado o contador de energia do core do Zen 4
  • O benchmark de largura de banda de instruções foi modificado para não usar CALL/RET durante a região de teste
    • Isso porque, com CALL/RET, o Zen 4 não usa o loop buffer
  • O teste foi fixado em um único core, e a potência média foi calculada lendo o Core Energy Status MSR antes e depois do salto para o array de teste
  • O Core Performance Boost foi desativado porque as leituras de energia variavam muito
  • Na BIOS antiga, o Core Energy Status MSR indicava consumo médio de 6W ao buscar NOPs do op cache, e consumo bem menor ao buscá-los do loop buffer
  • Mesmo ao aumentar o tamanho do array de teste até 128KB, cabendo no L2 e reduzindo a cobertura do op cache para menos de 1%, a potência média do core aparecia como 1,5W
    • Esse resultado não combina com uma situação em que deveria haver mais uso dos decodificadores e do caminho de fetch do L2
  • Na BIOS nova, o teste com op cache mostrou média de 1,68W, e o teste em que os decodificadores eram alimentados principalmente a partir do L2 mostrou quase o mesmo consumo
  • Os recursos de monitoramento de energia da AMD podem ser modelagem de energia, e não medição direta
    • O método de modelagem pode ter mudado entre versões de BIOS, ou o modelo pode não estar adequado
    • Não houve validação adicional por falta de hardware para medir diretamente em conectores como o 12V EPS

Motivo da desativação e visão para desenvolvedores

  • Não se sabe por que a AMD desativou o loop buffer do Zen 4
  • Às vezes recursos de CPU são desativados por causa de bugs de hardware
    • Houve o caso do LSD, o loop buffer do Intel Skylake, desativado por causa de um bug relacionado a acesso parcial a registradores em loops curtos com duas threads SMT ativas
  • O Zen 4 foi a primeira tentativa da AMD de colocar um loop buffer em uma CPU de alto desempenho, e validar uma primeira implementação é difícil
  • É possível que a AMD tenha encontrado internamente algum bug não exposto publicamente e desativado o loop buffer por precaução
  • O impacto em desempenho parece quase nulo ou muito pequeno, porque a largura de banda do op cache é suficiente
  • O impacto em energia é desconhecido, mas pode ser pequeno e difícil de medir
  • A AMD quase não documentou nem divulgou o loop buffer além de uma linha no Processor Programming Reference
    • Isso contrasta com a Intel, que costuma documentar seu loop buffer e recomendá-lo em guias de otimização para que desenvolvedores o aproveitem
  • O loop buffer do Zen 4 é um recurso limitado e menos útil que o op cache por causa da baixa capacidade e da limitação com CALL/RET
  • Se alguém quiser otimizar pensando no loop buffer do Zen 4 em BIOS antigas, pode considerar as seguintes condições
    • Manter loops com menos de 144 micro-ops
    • Considerar metade disso quando duas threads compartilham o mesmo núcleo físico
    • Avaliar inline para funções chamadas dentro de loops pequenos, evitando CALL/RET
  • Mesmo com essas otimizações, a chance é grande de não haver benefício prático

1 comentários

 
GN⁺ 2024-12-02
Opiniões no Hacker News
  • Fico especulando se esse recurso não foi desativado como uma tentativa de impedir uma vulnerabilidade de hardware ainda não divulgada

    • O texto também especula mais ou menos nessa linha: o Zen 4 foi a primeira tentativa da AMD de colocar um buffer de loop em CPUs de alto desempenho, e validar uma primeira implementação é sempre difícil
      Não é absurdo imaginar que a AMD tenha encontrado internamente um bug que ninguém havia esbarrado antes e, por excesso de cautela, tenha desligado o buffer de loop. Neste ponto do ciclo de vida do core, não consigo pensar em muitos outros motivos para a AMD mexer no front-end do Zen 4
    • Na prática, talvez mais coisas tenham sido desativadas. Os números são bem inesperados: no Cyberpunk 2077, ao rodar no die com VCache, os contadores de desempenho mostram IPC médio de 1,25 com o buffer de loop ligado e 1,07 com ele desligado, mas ainda assim há uma pequena queda de desempenho no BIOS novo
      Pessoalmente, isso me cheira a mitigação por microcódigo, mas, claro, é preciso esperar por um CVE
    • Desativar silenciosamente também é um grande risco. Porque isso sinaliza que eles sabiam da gravidade do problema e julgaram que era sério o bastante para aplicar um patch
      Se a vulnerabilidade não for divulgada, as partes afetadas não têm como começar a responder, exceto por pura paranoia. Divulgar uma vulnerabilidade também é uma forma de transferir a responsabilidade para o usuário final. É aquela lógica de “se você não atualizou, não reclame”. Raramente a divulgação leva à responsabilização pelo produto, e não me lembro de isso ter acontecido nem com Meltdown ou Spectre. Por isso, eu não concluiria que a AMD está escondendo de propósito
    • Parece ser a resposta certa, mas não posso dizer mais nada :(
  • O texto parece sugerir que o buffer de loop não traz ganho de desempenho nem de energia
    Nesse caso, pode ser o clássico caso de “uma equipe de engenharia passou meses criando um recurso novo e reluzente, ele não trouxe ganho real, mas alguém o lançou mesmo assim para salvar as aparências”. Já vi em equipes de software a ideia de reescrever uma base de código para eliminar inchaço legado e melhorar desempenho, só para no fim o número de linhas aumentar e o desempenho piorar. Em ambos os casos, não deveriam ter lançado

    • Ainda assim, o motivo de terem lançado é que ele podia ser desligado por uma atualização de firmware, e mudar significativamente o arranjo físico do hardware no meio do projeto provavelmente teria causado impactos piores
    • Se perceberam que ele não ajudava muito depois de já estar dentro do core, removê-lo em si certamente seria um risco claro
    • O texto também disse que foi difícil medir o consumo de energia de forma geral, então não dá para concluir que esse recurso não tenha efeito nenhum; na verdade, nem se deveria fazer isso
      É difícil acreditar que a equipe de engenharia da AMD fosse tão sem critério a ponto de gastar área e energia com um recurso de hardware sem valor algum; neste caso, eu tenderia a achar mais provável que o Chips 'n Cheese não tenha conseguido medir o impacto
    • Trabalho em uma empresa de hardware bastante conhecida, e o pessoal de software está obcecado em fazer alguma coisa, mesmo quando o benefício não foi suficientemente demonstrado fora de alguns casos de uso estreitos ou benchmarks direcionados
      É muito frustrante, mas ninguém quer gastar tempo fazendo investigação prévia. Empurrar um projeto novo costuma agradar mais a alta gestão e gerar menos perguntas
    • Também existe outra possibilidade: o benchmark de energia pode estar correto. O buffer economizava energia, mas depois encontraram, em nível de microcódigo, otimizações melhores que fizeram o caminho comum consumir menos energia, transformando o buffer em algo que passou a gastar energia
  • O parágrafo mais interessante do texto é este: a melhor maneira de enxergar o buffer de loop do Zen 4 é como um sinal de que a AMD tem capacidade sobrando para seus engenheiros tentarem coisas
    Talvez desta vez não tenha dado resultado, mas deixar engenheiros experimentarem com recursos de baixo risco e baixo impacto é uma boa forma de construir confiança. Espero ver mais dessa confiança daqui para frente

  • Sobre o trecho “Curiosamente, ao fixar no die non-VCache, desativar o buffer de loop reduz o desempenho em jogos em 5%. Não sei por quê”, fico pensando se medições mais refinadas de energia permitiriam saber se isso tem a ver com orçamento térmico/de energia
    Esse recurso também parece ter sido pensado para economizar energia

    • Aqui não há detalhes suficientes. O segundo CCD dos chips Ryzen, mesmo nos chips non-X3D, tem qualidade de binning inferior ao primeiro, e isso varia de chip para chip
      No meu chip non-X3D, a maioria dos cores do CCD0 chega a 5,6–5,75 GHz, mas os cores do CCD1 param em 5,4–5,5 GHz. Os chips V-Cache do Zen 4 têm uma penalidade grande de clock, mas o cache compensa mais do que isso. Seria preciso ver se testaram o CCD1 do mesmo chip com o recurso ligado e desligado, e se tentaram isolar outras mudanças, como correções de segurança; no texto, eles próprios admitem que “não”. Para fazer direito, seria necessário encontrar um jeito de desligar apenas esse recurso em um BIOS em que ele esteja habilitado e testar os dois cenários no mesmo chip; mesmo assim, por causa de outras condições de ramificação, o resultado talvez não fosse exato. Um perfil de desempenho completo melhoraria a precisão, mas provavelmente só engenheiros da AMD conseguiriam fazer isso
    • Eles disseram que o recurso foi desativado em algum ponto entre as duas versões de UEFI testadas. Como outras mudanças também devem ter sido incluídas, a medição não é um teste A/B rigoroso
  • Parece ter sido pequeno demais para fazer diferença real, e só tinha importância em situações muito específicas. Se o tornassem maior, o custo de implementação provavelmente seria alto demais em relação ao benefício
    Ainda assim, haveria uma pequena regressão em algumas cargas de trabalho, mas a AMD também tem feito pequenas melhorias de desempenho depois do lançamento. No Zen 4, isso deveria ter sido simplesmente uma opção no BIOS. O fato de aparentemente não terem feito isso sugere a possibilidade de bug ou problema de segurança

    • O fato de terem desativado silenciosamente um recurso que a maioria dos usuários nem perceberia, mas que aumenta a complexidade do front-end, dá a impressão de que puxaram esse chicken bit para evitar ou adiar a divulgação de um bug de hardware, ao mesmo tempo em que a mitigação já é distribuída. Malditos fornecedores, quando é que vão aprender
  • Como anedota, uma das poucas diferenças entre o 68000 de 1979 e o 68010 de 1982 era o “loop mode”, ou seja, a adição de um buffer de loop de 6 bytes

    • Muito mais importante foi a correção do suporte a MMU. O 68000 original perdia parte do estado necessário para se recuperar de uma falha de página, e a solução alternativa era feia e cara
      Consistia em executar duas CPUs defasadas em um ciclo e injetar uma interrupção recuperável na segunda CPU. Ainda assim, se você quisesse uma CPU com MMU, conjunto de instruções de 32 bits e barramento de endereços de 24 bits, parece que era mais barato do que as alternativas da época. Devem ter sido tempos realmente difíceis
    • Interessante. Para buffers de loop pequenos, gosto bastante dos núcleos Forth da GreenArrays
      Cabem 4 instruções em uma palavra de 18 bits, e um opcode decrementa o contador de loop e então volta para o início da palavra. Nesses casos, pode executar bem mais rápido
    • O buffer de loop do 68010 era quase inútil. Não só tinha apenas 6 bytes, como também comportava só duas instruções
      Uma delas tinha de ser a instrução de loop (DBcc), então o corpo do loop precisava ser uma única instrução. Na prática, quase a única coisa que podia ficar mais rápida era algo como um memcpy não otimizado
  • É interessante que, no Cortex-A15, isso seja um recurso central de projeto. Fico curioso se há números sobre o efeito em outros chips
    Em dispositivos com vida útil de projeto mais longa, como consoles, parece que ao menos poderia ser usado como alvo de otimização

    • Também tenho curiosidade. Eu esperaria que, em qualquer arquitetura RISC, os ganhos de um buffer de loop fossem relativamente pequenos
      Afinal, a ideia do RISC é que buscar e decodificar instruções seja muito mais fácil, ou quase trivial
  • Tenho um 7950X3D, para o qual fiz upgrade a partir de um Skylake 6700K. Parece que, inconscientemente, sou atraído por chips em que o buffer de loop por hardware foi desativado por software

    • Se um dia você for comprar uma máquina nova, seria bom avisar com antecedência. Para a gente conseguir evitar!
  • Artigo interessante, mas não sei quanto espaço o buffer de loop ocupa no die
    Fico pensando se, caso ele seja removido em chips futuros, esse espaço poderia ser usado para algo mais útil, como um cache L2 maior

    • Acho que, na maioria dos chips modernos, as restrições de fiação são maiores do que a área no piso. Dá para criar uma quantidade enorme de recursos, mas fornecer energia e sinais normalizados a tudo isso é realmente penoso
    • Pelo que entendo, é uma otimização bem pequena no front-end. Para começo de conversa, não há muitos itens, são 144, então a economia de espaço provavelmente seria mínima
      Em teoria, um buffer de loop pode economizar energia ou aumentar o desempenho em loops apertados. Na prática, parece não conseguir fazer nenhum dos dois, e a AMD o removeu completamente no Zen 5
    • Pelo diagrama, parece que o buffer de loop usa o mesmo armazenamento da fila de micro-operações que já existe de qualquer forma
      Se isso estiver certo, faz sentido, e o custo em área seria só alguma lógica de controle extra. A parte mais cara provavelmente é detectar o loop em primeiro lugar, mas ainda deve ser bem pequena em comparação com o tamanho da fila
    • Dizem que são 144 entradas de micro-operações por núcleo. Não sei quantos bytes isso representa, mas hoje os caches L2 têm cerca de 1 MB por núcleo, então, mesmo supondo que a área do die do buffer de loop seja majoritariamente armazenamento, não faria diferença perceptível
  • A análise da seção “energia” parece não ter sido dividida pelo número de instruções executadas por segundo
    Para ver os benefícios desse buffer de loop, é quase certo que seria preciso olhar para energia por instrução, não energia por segundo, ou seja, potência (watts)

    • Cada instrução leva um número diferente de ciclos de clock, e isso também muda entre gerações de arquitetura, como do Zen 4 para o Zen 5. Por isso, isso não é viável a menos que a carga de trabalho produza exatamente o mesmo número de instruções por ciclo, o que é impossível por causa do multithreading e do processamento das tarefas
      Até a ordem e o conteúdo da RAM podem mudar tudo. Dá para executar centenas de vezes com o recurso ligado e desligado para isolar um pouco, mas isso consome muito tempo e ainda assim não é 100% exato. Só desligar o recurso já pode fazer o código seguir um ramo diferente e mudar todo o layout. Não conheço este problema específico, mas já vi casos em que, ao desligar um recurso, a carga se deslocava das unidades inteiras para a FPU ou GPU, ou em que 5 instruções desapareciam, mas 2 eram adicionadas