Quando uma nova geração de processador é lançada, a maioria dos sites informa que os mecanismos e programas de jogos precisam ser otimizados para o novo hardware. Eu não entendo bem o porquê. Um processador geralmente possui uma arquitetura que define que tipo de conjunto de instruções ele usa. O que todos nós usamos hoje em dia é amd_x86_64. Por que qualquer programa ou compilador precisaria ser atualizado se todos os processadores usassem essa mesma arquitetura? Certamente, existem recursos dentro do pipeline do novo processador que otimizam a execução do código da máquina, mas por que o próprio código da máquina precisaria ser alterado se a arquitetura não o fizesse?
39
Respostas:
Porque diferentes gerações da mesma arquitetura pode ter diferentes conjuntos de instruções .
Por exemplo, as extensões Streaming SIMD são provavelmente o conjunto de instruções x86 mais conhecido, mas, ainda assim, e apesar de haver apenas uma arquitetura x86, existem SSE, SSE2, SSE3 e SSE4.
Cada uma dessas gerações pode incluir novas instruções que fornecem maneiras mais rápidas de executar determinadas operações. Um exemplo que seria relevante para os jogos pode ser as instruções do produto de ponto.
Portanto, se um mecanismo de jogo for compilado para uma geração anterior de uma arquitetura, ele não terá suporte para essas instruções mais recentes. Da mesma forma, pode ser necessário otimizar o mecanismo para obter instruções mais recentes; O SSE4 , por exemplo, tem suporte para instruções de produtos de ponto que funcionam com dados de matriz de estruturas. Uma otimização que poderia tirar proveito dessas instruções mais recentes seria alterar o layout dos dados para matriz de estruturas.
fonte
A resposta de Maximus está correta, só quero dar outra parte da história:
O próprio hardware muda de uma maneira que você precisa para alterar a forma como codifica, independentemente das instruções recém-introduzidas.
Aumento ou diminuição da quantidade de cache significa que você precisa se preocupar menos ou mais com problemas de otimização / invalidação de cache. Mais cache significa que, com dados pequenos, você pode se concentrar menos em garantir que os dados sejam contíguos sem se preocupar com o desempenho. Menos cache significa que isso pode ser um problema, e muito pouco cache significa que, com algumas estruturas de dados grandes, isso não importa.
Novos níveis de cache significam que você precisa pensar mais sobre como organizar conjuntos de dados ainda maiores (L1, vs L2, vs L3 vs L4).
Mais núcleos significa que você precisa pensar em como irá melhorar a aplicação de multiencadeamentos e como sua aplicação é escalada em um ambiente de multiprocessos.
Relógios mais rápidos significam que você precisa começar a pensar mais na latência da memória do que na velocidade de computação da CPU como um gargalo do seu sistema.
O número de FPUs em um sistema pode não mais corresponder ao número de ALUs inteiras por núcleo (a AMD tinha / tem arquiteturas como essa).
O número de ciclos de relógio necessários para calcular uma operação que diminuíram ou aumentaram.
O número de registros disponíveis foi alterado.
Tudo isso tem um impacto muito real no desempenho dos programas que fizeram suposições sobre a arquitetura subjacente no hardware anterior com o mesmo ISA, positivo ou negativo.
fonte
pdep
leva 1 ciclo na intel, mas 6 na Ryzen, portanto, pode não querer usá-la na Ryzen.c[i] = a[i] OP b[i]
(ou seja, 2 cargas e 1 armazenamento por operação), de modo que os tempos são dominados pela largura de banda da memória devido à intensidade computacional muito baixa. O tamanho da matriz não é mostrado, então IDK, se couber no L1D. (gcc4.9 -Ofast
muito provavelmente auto-vetorizou esses loops, então você nem está medindo o custo de operações escalares normais como parte de um código inteiro complexo). A primeira linha dessa página é IMPORTANTE: O feedback útil revelou que algumas dessas medidas são seriamente falhas. Uma grande atualização está a caminho .Mesmo além de grandes mudanças, como o suporte a novas instruções, os fabricantes de microprocessadores estão constantemente modificando seus projetos para melhorar o desempenho, e cada novo design pode ter um desempenho relativo diferente para cada instrução ou técnica. Talvez você tenha escrito algum código sem ramificação cuidadosamente otimizado para o Modelo X, mas o Modelo Y possui um preditor de ramificação aprimorado que reduz a penalidade de erro de previsão para a versão sem ramificação do código (que também libera um registro para ser usado em outro lugar) . Talvez o Modelo Y suporte maior paralelismo de uma determinada instrução de alta latência, de modo que agora um loop desenrolado dessa instrução obtenha uma melhor taxa de transferência, enquanto no Modelo X uma sequência mais curta foi melhor.
Qualquer problema pode ser resolvido de várias maneiras, e todo programa é uma coleção interligada de trocas e alocações de recursos, do ponto de otimização. Mesmo pequenas alterações na disponibilidade desses recursos ou no custo de um determinado trecho de código em termos desses recursos, podem ter um efeito em cascata que oferece uma vantagem substancial de desempenho para um trecho de código ou outro. Mesmo se um chip atualizado tem "mais de tudo", como muito mais de cada coisa pode balançar o equilíbrio.
fonte