Como uma CPU pode fornecer mais de uma instrução por ciclo?


41

A página Instruções da Wikipedia por segundo diz que um i7 3630QM fornece ~ 110.000 MIPS a uma frequência de 3,2 GHz; seria (110 / 3,2 instruções) / 4 núcleos = ~ 8,6 instruções por ciclo por núcleo ?! Como um único núcleo pode fornecer mais de uma instrução por ciclo?

Para meu entendimento, um pipeline deve ser capaz de fornecer apenas um resultado por relógio.

Estes são os meus pensamentos:

  • A frequência interna é realmente superior a 3,2 GHz
  • Algumas partes da CPU são assíncronas de uma maneira que um humano humilde como eu não consegue entender
  • Existem vários pipelines simultâneos por núcleo
  • Um pipeline pode fornecer mais do que o resultado por relógio, uma instrução pode pular os estágios do pipeline e há vários pré-buscadores para acompanhar
  • Estou faltando alguma coisa

1
Ele fornece 110.000 MIPS Dhrystone , então DMIPS, não MIPS, é algo que eu vejo diretamente - talvez isso possa fazer a diferença? Veja en.wikipedia.org/wiki/Dhrystone

Respostas:


44

Primeiro, como apontam o comentário de Keelan e a resposta de Turbo J , a medição foi de 113.093 MIPS Dhrystone e não MIPS nativo .

A microarquitetura Ivy Bridge do i7 3630QM pode confirmar apenas 4 µops fundidos por ciclo, embora possa começar a execução de 6 µops por ciclo. (O número de µops fundidos em um traço de código é aproximadamente igual ao número de instruções; algumas instruções complexas são decodificadas em vários µops que não são fundidos e alguns pares de instruções podem ser fundidos em um único µop, por exemplo, uma comparação imediata seguido de um salto condicional.)

Duas de suas especulações sobre como várias instruções podem ser executadas em um único ciclo são bastante válidas e foram usadas em processadores reais. Sua primeira especulação, de que um relógio interno mais rápido é usado, foi usada nas ALUs originais de "bola de fogo" do Pentium 4. Essas ULAs tinham frequência de clock duas vezes maior que a do resto do núcleo, que já era relativamente alto.

(Isso foi realizado usando uma ULA escalonada na qual a metade inferior de uma adição foi feita em um ciclo, permitindo que uma operação dependente use a metade inferior do resultado no próximo ciclo. Para operações como adição, xor ou deslocamento à esquerda que apenas precisam da metade inferior dos operandos para produzir a metade inferior completa do resultado, esse escalonamento - também conhecido como pipelining de largura - permite latência de resultado de ciclo único e taxa de transferência de ciclo único).

Uma técnica um pouco relacionada, ALUs em cascata, foi usada pelo HyperSPARC. O HyperSPARC alimentou os resultados de duas ALUs em uma terceira ALU. Isso permitiu que duas operações independentes e uma terceira dependente fossem executadas em um único ciclo.

Sua especulação de que "existem vários pipelines simultâneos por núcleo" é a outra técnica usada. Esse tipo de design é chamado superescalar e é de longe o meio mais comum de aumentar o número de operações executadas em um único ciclo.

Existem também algumas outras probabilidades e fins de execução de instruções que podem ser dignos de nota. Algumas operações podem ser executadas com mais eficiência fora das unidades de execução comuns. A técnica de eliminação de movimentação explora o uso da renomeação de registradores em processadores fora de ordem para executar operações de movimentação durante a renomeação de registradores; a movimentação simplesmente copia o número do registro físico de uma posição na tabela de renomeação (chamada tabela de alias de registro) para outra. Isso não apenas aumenta efetivamente a largura de execução, mas também remove uma dependência. Essa técnica foi usada no início com o x87 baseado em pilha, mas agora é amplamente usada nos processadores x86 de alto desempenho da Intel. (O uso de instruções destrutivas de dois operandos no x86 torna a eliminação de movimentos mais útil do que seria em um RISC típico.)

Uma técnica semelhante à eliminação de movimentação é a manipulação das instruções de zerar o registro durante a renomeação. Ao fornecer um nome de registro que forneça o valor zero, uma instrução de limpeza de registro (como xor ou subtrair com os dois operandos sendo o mesmo registro) pode simplesmente inserir esse nome na tabela de renomeação (RAT).

Outra técnica usada por alguns processadores x86 reduz o custo de operações push e pop. Normalmente, uma instrução usando o ponteiro da pilha teria que esperar um ciclo completo por um push ou pop anterior para atualizar o valor do ponteiro da pilha. Ao reconhecer que push e pop apenas adicionam ou subtraem um pequeno valor ao ponteiro da pilha, é possível calcular os resultados de várias adições / subações em paralelo. O principal atraso da adição é a propagação de transporte, mas com valores pequenos, os bits mais significativos do valor base - nesse caso, o ponteiro da pilha - terão apenas no máximo um transporte. Isso permite que uma otimização semelhante à de um somador carry-select seja aplicada a várias adições de pequenos valores. Além disso, como o ponteiro da pilha geralmente é atualizado apenas por constantes,

Também é possível mesclar instruções em uma operação única e mais complexa. Embora o processo inverso de dividir as instruções em várias operações mais simples seja uma técnica antiga, as instruções de mesclagem (que a Intel chama de fusão de macro-operações) podem permitir que a implementação ofereça suporte a operações mais complexas do que as expostas no conjunto de instruções.

Do lado teórico, outras técnicas foram propostas. Pequenas constantes diferentes de zero podem ser suportadas no RAT e algumas operações simples que usam ou produzem valores pequenos e confiáveis ​​podem ser tratadas antecipadamente. ("Physical Register Inlining", Mikko H. Lipasti et al., 2004, sugeriu o uso do RAT como um meio de reduzir a contagem de registros, mas a idéia poderia ser estendida para suportar o carregamento de pequenos imediatos e operações simples em pequenos números.)

Para caches de rastreio (que armazenam sequências de instruções sob premissas específicas do fluxo de controle), pode haver oportunidades para mesclar operações separadas por ramificações e remover operações que produzam resultados não utilizados no rastreio. O armazenamento em cache das otimizações em um cache de rastreamento também pode incentivar a execução de otimizações, como a mesclagem de instruções, que pode não valer a pena se elas precisassem ser feitas sempre que o fluxo de instruções fosse buscado.

A previsão de valor pode ser usada para aumentar o número de operações que podem ser executadas em paralelo, removendo dependências. Um preditor de valor baseado em passada é semelhante à otimização pop / push de um mecanismo de pilha especializado mencionado anteriormente. Ele pode calcular várias adições principalmente em paralelo, removendo a serialização. A idéia geral de previsão de valor é que, com um valor previsto, as operações dependentes podem prosseguir sem demora. (A direção da ramificação e a previsão do alvo são efetivamente apenas uma forma muito limitada de previsão de valor, permitindo a busca das instruções a seguir, que dependem do "valor" da ramificação - obtida ou não - e do endereço da instrução seguinte, outro valor.)


impressionante! Obrigado pela informação valiosa. Você poderia sugerir um livro onde eu possa ler todas essas técnicas de arquitetura?
sem trabalho

@workless Depois de ir além do básico de pipelining e execução superscalar fora de ordem (que seria coberta pela maioria dos livros de arquitetura de computadores), as melhores fontes de informação provavelmente são descrições de microarquiteturas de processadores específicas (como o artigo sobre Haswell na resposta de gnasher729 ) e trabalhos acadêmicos (ISCA e MICRO [conferências] geralmente têm bons trabalhos; HPCA, PACT, ASPLOS e talvez alguns outros também têm boa reputação). Andy Glew (talvez o mais famoso por seu trabalho sobre o Pentium Pro) ...
Paul A. Clayton

1
... estava trabalhando em um wiki do CompArch, que apresentaria conceitos mais avançados, mas o progresso foi lento e, aparentemente, foi hackeado há um tempo atrás e agora agora apenas fornece uma mensagem de erro ( semipublic.comp-arch.net/wiki ). Ele pretende restabelecer o wiki (o texto original foi preservado) usando um software wiki diferente (ele teve alguns problemas com o software que estava usando e está aproveitando isso como uma oportunidade para fazer melhorias), mas "Vai demorar um pouco".
Paul A. Clayton

Um bom exemplo do sucesso da arquitetura superescalar foi o HyperThreading da Intel - com todas essas otimizações, os engenheiros da Intel descobriram que cerca de 30% da ALU não era usada na maioria das vezes, porque a memória não pode fluir com rapidez suficiente ou o o pipeline não pode ser preenchido com eficiência suficiente. O HyperThreading permite que você trabalhe de graça no cenário ideal. É muito menos do que ter um novo núcleo separado, mas também é muito mais barato (e também pode ser combinado com vários núcleos).
Luaan

@ PaulA.Clayton - duas capturas dessa página estão no Wayback. 20 de dezembro de 2013 e 14 de fevereiro de 2014 . Não sei se essas capturas são anteriores aos problemas da página. Infelizmente, quando tentei visitar essas páginas no Wayback, recebi a mensagem " Bummer. A máquina que serve esse arquivo está inoperante. Estamos trabalhando nisso. ", Então não tenho certeza do que pode ser visto nessas páginas. .
Kevin Fegan

10

Alguma magia negra acontece no interior dos processadores modernos, mas seus pensamentos estão definitivamente na linha certa.

A chave para entender a eficiência dos processadores modernos é perceber que eles são superescalares . Da Wikipedia (ênfase minha):

Uma arquitetura de CPU superescalar implementa uma forma de paralelismo chamada paralelismo em nível de instrução em um único processador. Portanto, permite uma taxa de transferência mais rápida da CPU do que seria possível em uma determinada taxa de clock.

Esses processadores modernos têm várias unidades de execução por núcleo, como você adivinhou. Hyper-Threading é interessante considerar, algumas partes do gasoduto são duplicados, mas alguns não são.

Também é interessante ler sobre execução fora de ordem , mas não responde diretamente à sua pergunta. No entanto, reduz o número de ciclos "desperdiçados" da CPU.

A eficiência também é afetada por muitas outras coisas que podem causar uma paralisação dentro do processador, incluindo (mas definitivamente não se limitando a):

  • Os resultados das instruções anteriores não estão disponíveis.
  • Falha no cache.
  • A ramificação de código, que invalidaria as instruções já buscadas (leia sobre a previsão de ramificação aqui e aqui ).

Compiladores modernos tentam ajudar com muitos dos itens acima, e o processador assume o controle. Para um bom exemplo, consulte esta pergunta em outro lugar no Stackexchange, que destaca uma diferença importante entre duas instruções que podem fazer a mesma coisa (em algumas circunstâncias). No entanto, um pode ser "mais rápido" do que o outro em alguns processadores devido à unidade de execução em uso.

Para uma explicação legível por humanos do pipeline de CPU moderno, consulte Uma jornada pelo pipeline de CPU . Para uma explicação um pouco mais técnica, consulte o artigo sobre microarquitetura de Agner Fog .


obrigado pela explicação e pelos links muito interessantes. Como uma nota, Cell parece muito interessante, estou ansioso para estudar mais sobre arquiteturas de CPU ^ _ ^. "" O x86 usa uma "superpipeline" como descrito acima. A família Cell usa uma abordagem "sinérgica" envolvendo nove mini-cpus. É verdade que cada minicomputador segue um pipeline principalmente em ordem, o minicomputador tem vários pipelines superscalares paralelos em vez de um pipeline único. "" "
sem trabalho

3

O que você acha que aconteceu: todos os engenheiros da Intel, AMD e IBM leram que um pipeline pode fornecer apenas um resultado por ciclo e disseram "oh bem, é isso, então, não podem tornar esses processadores mais rápidos". Ou eles leram isso e disseram: "Não é possível obter mais de um resultado por ciclo? Vamos ver isso!".

Para uma boa introdução à arquitetura Haswell, por exemplo, você pode seguir este link http://www.realworldtech.com/haswell-cpu/ ou você pode simplesmente acessar o site da Intel e encontrará uma documentação aqui.

Cada núcleo do processador Haswell possui um grande número de unidades de execução, que podem executar operações independentemente uma da outra, para que várias operações possam ser executadas em paralelo. Em seguida, o processador Haswell possui várias unidades de execução que manipulam operações vetoriais de até 256 bits. Uma operação vetorial pode, por exemplo, executar quatro operações de ponto flutuante de precisão dupla ou oito operações de ponto flutuante de precisão única em uma operação vetorial. E, finalmente, o processador Haswell suporta "multiply-add fundido", o que significa que calcular vezes b mais c é apenas uma operação.

O máximo teórico, já que a Haswell possui duas unidades capazes de adição múltipla combinada, são duas operações de adição múltipla fundida por ciclo, cada operação fazendo oito multiplicações de precisão única mais adições ou 32 operações de ponto flutuante de precisão única.

O processador 3630 não está na lista de preços mais recente da Intel, mas existem modelos como o 3740QM com quatro núcleos. Portanto, em vez de 32, você pode obter 128 operações de ponto flutuante por ciclo de clock. Este é o máximo teórico. Conseguir metade disso na vida real é um desafio, mas não impossível para tarefas adequadas. Existem outros processadores disponíveis com até 15 núcleos (por preços que nem mesmo os fanáticos por jogos mais fanáticos pagam).

Então você tem uma combinação de vários multiplicadores:

  1. Vários núcleos por processador.
  2. (O hyperthreading, não mencionado anteriormente, permite que você se aproxime dos limites teóricos)
  3. A operação de adição múltipla combinada realiza duas operações aritméticas contando apenas como uma.
  4. Vetores de 256 bits realizando 8 operações contando apenas como uma.
  5. Duas unidades de execução de vetor capazes de lidar com adição com multiplicação por fusão.

8,6 operações por ciclo não é muito difícil de alcançar. Mesmo 8,6 operações por ciclo por núcleo não são muito difíceis.


Gostaria de saber se seria prático ou vantajoso projetar uma CPU com alguns núcleos que rodavam x86 e outros que rodavam um conjunto de instruções otimizado para o comportamento superescalar. Eu sei que a Intel e a AMD fazem coisas incríveis para solucionar as limitações do conjunto de instruções x86, mas em alguns casos eu pensaria que seria útil conhecer algumas coisas que o conjunto de instruções atual não pode expressar. Por exemplo, versões distintas de ADDinstruções com base em se o estouro deve ser deixado inalterado ou deve ser definido quando ocorrer um estouro (e deixado definido se não ocorrer).
Supercat

1
Sinto-me entristecido pelo fato de que hoje em dia, muitos idiomas são o padrão para não verificar o estouro. Eu sei que o Java está praticamente preso a requisitos semânticos, mas em linguagens como C # que incluem operadores aritméticos de trapping e non-trapping, a única boa razão que vejo para não prender o estouro é porque é necessário um comportamento de empacotamento. Atualmente, a verificação de estouro pode impor uma penalidade de velocidade significativa, mas se uma linguagem de máquina fosse projetada com base na idéia de que o trapping de estouro não precisa ser preciso, desde que o código possa garantir que nenhum estouro tenha ocorrido antes da operação ...
supercat

... atinge certos pontos críticos, deve ser possível reduzir a sobrecarga de captura de sobrecarga para quase zero. Se o código executar uma computação e, em seguida, armazenar um valor em um local que será abandonado se o primeiro cálculo for excedido, não será necessário adiar o armazenamento até que o processador saiba se o primeiro cálculo foi bem-sucedido, mas atualmente o processador não tem como de saber isso. Se o código poderia simplesmente fazer todas as operações que podem seguramente ser realizados ou não estouro tenha ocorrido, e, em seguida, verificar se todos os excessos indevidos ocorreram em qualquer um deles ...
supercat

... isso parece ajudar a reduzir as dependências de execução.
Supercat

2

O valor de referência Drystone é de 1984, e a máquina nominal correspondente de 1 MIPS VAX não é muito eficiente em termos modernos. Até um Cortex M3 oferece 1,25 DMPIS / MHz.

Os processadores de arquitetura Intel Core podem realmente executar várias instruções em paralelo em um único núcleo, porque existem várias unidades de computação presentes.


1

Aprendi muito com Jon "Hannibal" Stokes, da Ars Technica, excelentes e extensos artigos sobre o assunto da arquitetura de microprocessadores. Os artigos são um pouco datados (parecem ser de 2004), mas ainda são muito relevantes.

Alguns dos links para a próxima parte de um artigo estão quebrados, mas parece que você pode corrigi-los comparando cuidadosamente o URL da primeira parte e o URL quebrado da página seguinte (por exemplo, adicionando m-algum lugar ao URL).

(sim, esta é uma resposta somente para links glorificados, desculpe; os artigos são bons demais para não mencioná-los)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.