Processadores paralelos e de múltiplos núcleos

Aprenda por que os processadores passaram a usar paralelismo e como os computadores atuais dividem o trabalho entre muitas unidades ao mesmo tempo. Compare o paralelismo em nível de instrução, dados, thread e requisição, classifique máquinas pela taxonomia de Flynn e calcule os limites da aceleração com as leis de Amdahl e Gustafson e o modelo Roofline. Veja como instruções SIMD e vetoriais, GPUs, chips de múltiplos núcleos com caches coerentes, aglomerados de computadores e computadores em escala de centro de dados transformam hardware paralelo em computação mais rápida ou mais barata, com exemplos resolvidos que você pode conferir à mão.

IntermediárioAula 6 de 6 do curso Curso de Organização e arquitetura de computadores

O que você vai aprender

  1. Explicar por que os processadores passaram a usar paralelismo, distinguir o paralelismo em nível de instrução, dados, thread e requisição, classificar máquinas pela taxonomia de Flynn e descrever como o multithreading em hardware mantém um núcleo ocupado.
    • Explicar por que os computadores passaram a usar paralelismo e identificar seus tipos
      Relacionar a barreira de potência à transição para chips de múltiplos núcleos e reconhecer o paralelismo em nível de instrução, dados, thread e requisição em programas reais.
    • Classificar hardware paralelo com a taxonomia de Flynn
      Usar o número de fluxos de instruções e de dados para classificar uma máquina como SISD, SIMD, MISD ou MIMD e explicar o estilo de programação SPMD.
    • Manter um núcleo ocupado com multithreading em hardware
      Explicar como o multithreading de granularidade fina, de granularidade grossa e simultâneo oculta paradas e como threads de hardware diferem de núcleos adicionais.
  2. Calcular aceleração e eficiência, aplicar as leis de Amdahl e Gustafson, considerar desequilíbrio de carga e sobrecarga e usar o modelo Roofline para verificar se a capacidade de cálculo ou a largura de banda da memória limita um programa.
    • Calcular a aceleração e a eficiência com a lei de Amdahl
      Definir aceleração e eficiência, aplicar a lei de Amdahl nos dois sentidos e explicar por que a fração sequencial limita a aceleração de um problema de tamanho fixo.
    • Distinguir escalabilidade forte e fraca e considerar as sobrecargas
      Comparar a aceleração com tamanho fixo e com tamanho escalonado, aplicar a lei de Gustafson e estimar o efeito do desequilíbrio de carga, da comunicação e da sincronização.
    • Determinar limites de desempenho com o modelo Roofline
      Calcular a intensidade aritmética, ler um gráfico Roofline para decidir se um kernel é limitado pela largura de banda da memória ou pela capacidade de cálculo de pico e escolher otimizações adequadas.
  3. Usar instruções SIMD e arquiteturas vetoriais para processar vetores, explicar como uma GPU é organizada para obter alta vazão e escrever e analisar um kernel simples de GPU.
    • Processar vários elementos de dados ao mesmo tempo com instruções SIMD
      Calcular quantas vias um registrador SIMD tem, vetorizar laços simples e reconhecer as organizações de dados, os desvios e as dependências que limitam a aceleração SIMD.
    • Explicar como arquiteturas vetoriais executam laços
      Descrever registradores vetoriais, comprimento do vetor, particionamento do laço em blocos, vias e acesso com passo constante, usando a extensão vetorial RISC-V como exemplo.
    • Descrever como uma GPU é organizada para obter alta vazão
      Explicar multiprocessadores de streaming, warps e execução SIMT, como GPUs ocultam a latência da memória, divergência de desvios, coalescência de acessos à memória e custo da transferência de dados, e comparar GPUs com CPUs e aceleradores de domínio específico.
    • Escrever e analisar um kernel simples de GPU
      Usar a hierarquia de grade, bloco e thread para mapear dados às threads, organizar o trabalho do hospedeiro e do dispositivo e sincronizar dentro de um bloco.
  4. Descrever multiprocessadores de memória compartilhada e como as threads dividem o trabalho, explicar as garantias da coerência de cache, acompanhar protocolos de monitoração e de diretório e evitar falso compartilhamento.
    • Descrever multiprocessadores de memória compartilhada e dividir o trabalho entre núcleos
      Explicar um espaço de endereçamento compartilhado único, o acesso uniforme e não uniforme à memória, a organização das caches de um chip de múltiplos núcleos e como as threads dividem e combinam o trabalho.
    • Explicar o problema da coerência de cache e as garantias da coerência
      Mostrar como caches privadas podem retornar dados desatualizados, apresentar as condições de um sistema de memória coerente e distinguir coerência de consistência e de código livre de condições de corrida.
    • Acompanhar um protocolo de monitoração de coerência com estados MSI e MESI
      Acompanhar estados de blocos de cache e transações no barramento em uma sequência de leituras e escritas e explicar o que o estado exclusivo economiza.
    • Explicar protocolos baseados em diretório e evitar falso compartilhamento
      Descrever como um diretório rastreia os detentores de cópias, estimar seu custo de armazenamento e reconhecer, medir e corrigir o falso compartilhamento.
  5. Descrever aglomerados de computadores com passagem de mensagens e comparar redes de interconexão por largura de banda e custo; depois, explicar como computadores em escala de centro de dados fornecem serviços de internet, considerando custo, energia e falhas.
    • Descrever aglomerados de computadores com passagem de mensagens e comparar redes de interconexão
      Explicar como nós com memórias privadas cooperam por mensagens e comparar topologias de rede por largura de banda total, largura de banda de bisseção e custo.
    • Explicar como computadores em escala de centro de dados fornecem serviços em grande escala
      Descrever a organização de um computador em escala de centro de dados e analisar sua rede, seu uso de energia e suas falhas com cálculos simples.

Guia de estudo de Processadores paralelos

5 capítulos

1

Identifique e classifique o trabalho paralelo

O hardware paralelo pode trabalhar com instruções, elementos de vetores, threads ou requisições independentes. A escolha útil depende de onde um programa tem trabalho que pode ser executado em conjunto. Relacione esse trabalho aos limites de potência que levaram os chips a ter múltiplos núcleos e depois classifique o hardware por seus fluxos de instruções. O multithreading em hardware oferece outra forma de manter um núcleo ocupado ao encontrar instruções úteis durante as paradas.

1.1 Por que os chips agora dividem o trabalho

Computadores paralelos realizam operações ao mesmo tempo. Eles podem reduzir a latência, o tempo que uma tarefa leva, ou aumentar a vazão, o número de tarefas concluídas por segundo. Esses objetivos levam a formas diferentes de dividir o trabalho.

A barreira de potência

Aumentar a frequência de clock antes tornava cada geração de processadores mais rápida. A potência dinâmica segue aproximadamente P≈CV2f: capacitância vezes tensão ao quadrado vezes frequência de chaveamento. A tensão aparece duas vezes nesse produto. Reduzir tanto a tensão quanto a frequência em 15% resulta em 0,852×0,85=0,614125 da potência dinâmica original, cerca de 61%.

A tensão não podia continuar caindo o suficiente para compensar frequências de clock mais altas. A corrente de fuga e o calor tornaram custoso demais continuar aumentando a frequência. Essa barreira de potência levou a indústria aos chips de múltiplos núcleos em meados dos anos 2000. Um chip de múltiplos núcleos coloca vários núcleos de processador em um chip; um sistema multiprocessador tem pelo menos dois processadores. Núcleos mais modestos podem realizar mais trabalho total por joule, desde que haja trabalho suficiente para dividir.

Quatro fontes de trabalho paralelo
TipoO que é executado em conjunto?Exemplo
Paralelismo em nível de instrução (ILP)Instruções de um fluxo de instruçõesUm pipeline sobrepõe estágios de instruções sucessivas.
Paralelismo em nível de dados (DLP)A mesma operação em muitos elementosSomar elementos correspondentes de dois vetores.
Paralelismo em nível de thread (TLP)Várias sequências de instruçõesVárias threads processam regiões diferentes de uma imagem.
Paralelismo em nível de requisiçãoTarefas independentesServidores respondem às consultas de muitos usuários ao mesmo tempo.

O ILP é identificado principalmente pelo hardware e pelos compiladores. A segmentação em pipeline, a emissão múltipla e a execução fora de ordem sobrepõem instruções enquanto preservam os resultados exigidos pelo programa. Dependências e desvios limitam a sobreposição disponível.

O DLP aparece quando muitos elementos precisam do mesmo cálculo. Instruções SIMD, processadores vetoriais e GPUs exploram essa regularidade. O TLP exige que o trabalho seja dividido em threads pelo código, por uma biblioteca ou por um compilador. Uma thread tem seu próprio contador de programa, registradores e pilha; threads de um mesmo processo compartilham seu espaço de endereçamento. Processos distintos têm espaços de endereçamento distintos.

O trabalho em nível de requisição precisa de pouca cooperação entre tarefas. Adicionar servidores pode, portanto, aumentar a capacidade quase proporcionalmente aos recursos acrescentados. Executar vários programas independentes em um notebook também usa núcleos que estariam ociosos, aumentando a vazão geral mesmo quando nenhum desses programas é paralelizado internamente.

Tarefas concorrentes e execução simultânea

Concorrência significa que tarefas progridem durante períodos sobrepostos. Um núcleo pode fazer isso alternando entre elas. Paralelismo significa que operações são executadas no mesmo instante em unidades de hardware distintas. Um sistema de núcleo único pode manter vários programas em andamento sem executar suas instruções simultaneamente.

Um programa com uma thread sequencial não se divide entre oito núcleos simplesmente porque eles existem. Os núcleos extras podem executar outro trabalho, mas reduzir o tempo desse programa exige trabalho paralelo dentro dele. Mesmo depois que o trabalho é dividido, qualquer parte sequencial restante ainda limita o ganho.

Principais conclusões

  • O hardware paralelo pode reduzir a latência de uma tarefa ou aumentar a vazão total.
  • A potência dinâmica depende da tensão ao quadrado e da frequência.
  • ILP, DLP, TLP e paralelismo em nível de requisição revelam tipos diferentes de trabalho.
  • A concorrência pode usar compartilhamento de tempo; o paralelismo usa execução simultânea.

1.2 Conte os fluxos de instruções e de dados

Um processador pode conter muitas unidades aritméticas sem seguir muitos fluxos de instruções independentes. A taxonomia de Flynn classifica o hardware por seus fluxos de instruções e de dados, portanto o primeiro passo é escolher o nível da máquina que está sendo descrito.

As quatro classes de hardware
ClasseFluxos de instruçõesFluxos de dadosSignificado
SISDÚnicoÚnicoUm processador segue um fluxo de instruções comum.
SIMDÚnicoMúltiplosUma instrução aplica uma operação a vários elementos de dados.
MISDMúltiplosÚnicoFluxos de instruções diferentes operam sobre um fluxo de dados.
MIMDMúltiplosMúltiplosProcessadores buscam instruções e trabalham com dados de forma independente.

Um processador convencional de núcleo único é SISD mesmo quando seu pipeline sobrepõe várias instruções. A emissão superescalar, por si só, não cria contadores de programa independentes nem transforma o núcleo em hardware MIMD.

Uma instrução SIMD pode somar oito pares de números de ponto flutuante de 32 bits em um registrador de 256 bits. Ela tem oito vias aritméticas, mas elas seguem uma instrução. Extensões SIMD de largura fixa incluem x86 SSE e AVX e Arm Neon; arquiteturas vetoriais também se enquadram na classe SIMD. Cálculos regulares em vetores são adequados porque muitos elementos precisam da mesma operação.

Processadores MIMD escolhem suas instruções independentemente. Chips de múltiplos núcleos, multiprocessadores de memória compartilhada e aglomerados de computadores se enquadram nessa classe. Os núcleos podem executar programas diferentes ou cópias do mesmo programa que chegam a desvios diferentes em momentos diferentes.

MISD completa a classificação dois por dois. Há poucos exemplos práticos claros. Alguns sistemas tolerantes a falhas e pipelines de processamento são descritos dessa forma, mas sua classificação depende de como seus fluxos são definidos.

Um programa ainda pode ter muitos fluxos de instruções

SPMD, programa único e múltiplos dados, é um estilo de programação. Cada unidade de trabalho executa uma cópia do mesmo programa e usa seu identificador para selecionar sua parcela dos dados. As unidades têm estados de execução independentes, portanto SPMD normalmente é executado em hardware MIMD.

Para quatro núcleos somando 4.000 valores, o núcleo de identificador i trata os índices de 1000i a 1000i+999. O núcleo 0 trata de 0 a 999; o núcleo 3 trata de 3000 a 3999. Cada um produz uma soma parcial, e essas quatro somas são combinadas. O texto compartilhado do programa não exige que os quatro núcleos emitam a mesma instrução no mesmo ciclo.

Classifique cada nível separadamente

Considere uma CPU de oito núcleos cujas threads usam instruções AVX. Entre os núcleos, ela é MIMD: os núcleos avançam independentemente. Dentro de uma operação AVX, ela é SIMD: uma instrução controla várias vias. Contar todas as unidades aritméticas juntas ocultaria essa estrutura.

Um aglomerado que executa cópias de um programa científico também é hardware MIMD usando software SPMD. Seus nós se comunicam por mensagens. Uma GPU combina muitos grupos de threads escalonados independentemente com execução semelhante a SIMD dentro de cada grupo; a NVIDIA chama seu estilo de execução baseado em threads de SIMT.

Para classificar uma descrição, pergunte quem escolhe a próxima instrução. Depois, pergunte se essa instrução processa um elemento de dados ou vários. O número de arquivos-fonte, programas instalados ou unidades aritméticas, por si só, não responde a essas duas perguntas.

Principais conclusões

  • A taxonomia de Flynn conta os fluxos de instruções e os fluxos de dados.
  • A segmentação em pipeline dentro de um fluxo de instruções continua sendo SISD.
  • SIMD compartilha o controle de instruções entre vias; MIMD tem fluxos de instruções independentes.
  • SPMD é um estilo de programação normalmente executado em hardware MIMD.
  • Uma máquina pode ser MIMD entre núcleos e SIMD dentro de cada núcleo.

1.3 Preencha ciclos ociosos com outra thread

Uma falta na cache pode deixar um núcleo esperando centenas de ciclos. O multithreading em hardware mantém os estados de execução de várias threads dentro de um núcleo para que instruções úteis de outra thread possam ser executadas durante essa espera.

O que é duplicado e o que é compartilhado

Cada thread de hardware tem seu próprio contador de programa e estado de registradores. As threads compartilham as unidades de execução, as caches e o acesso à largura de banda da memória do núcleo. Manter o estado no hardware torna a troca muito mais rápida do que salvar e restaurar um processo do sistema operacional, o que pode custar milhares de ciclos. O hardware pode fazer a troca em um ciclo ou menos.

O sistema operacional vê cada thread de hardware como um processador lógico. Oito núcleos físicos com duas threads de hardware por núcleo apresentam 16 processadores lógicos. Essa contagem descreve os contextos de thread disponíveis, não 16 núcleos físicos completos.

Três formas de escalonamento
AbordagemQuando o núcleo escolhe outra thread?Principal compromisso
Granularidade finaA cada ciclo, pulando threads paradasOculta paradas curtas e longas, mas cada thread espera entre suas vezes.
Granularidade grossaEm uma parada longa, como uma falta na cache de último nívelDá longos períodos de execução a uma thread, mas a troca e o preenchimento do pipeline custam tempo.
Multithreading simultâneo (SMT)Várias threads podem emitir instruções no mesmo cicloPreenche posições de emissão não usadas enquanto compartilha os recursos do núcleo.

O escalonamento de granularidade fina pode alternar entre threads prontas mesmo quando a thread anterior poderia continuar. O escalonamento de granularidade grossa continua executando essa thread até que uma parada custosa justifique a troca. O SMT usa um núcleo com emissão múltipla e escalonamento dinâmico: instruções de threads diferentes podem ocupar posições livres de emissão diferentes durante um ciclo. A renomeação de registradores mantém seus estados separados. O Hyper-Threading da Intel é uma implementação de SMT; alguns processadores IBM POWER suportam oito threads de hardware por núcleo.

Analise a ocultação de latência

Suponha que uma thread calcule por 20 ciclos e depois espere 200 ciclos pela memória. Seu ciclo tem 220 ciclos de duração. Sozinho, o trabalho útil ocupa 20/220≈0,091, ou 9,1% do tempo.

Com quatro threads, trabalho escalonado livremente e sem custo de troca ou disputa adicional, o trabalho útil pode ocupar 4×20/220≈0,364, ou 36,4%. O núcleo ainda tem intervalos ociosos porque quatro períodos de 20 ciclos não conseguem cobrir os períodos de espera.

Onze threads fornecem 220 ciclos de períodos de cálculo no total. Enquanto uma espera por 200 ciclos, as outras dez podem calcular por 20 cada uma. Esse escalonamento ideal mantém o núcleo ocupado. O desempenho real também depende de essas threads competirem ou não por recursos de memória e execução.

Vazão e tempo de conclusão de uma thread

O multithreading aumenta principalmente a vazão. Uma thread específica pode levar mais tempo porque outras threads usam ciclos e espaço de cache que ela receberia de outra forma. Duas threads de hardware que compartilham uma unidade aritmética não podem receber, ambas, a capacidade de um segundo núcleo completo.

Se ambas as threads já exigem as mesmas unidades de execução totalmente ocupadas, o SMT tem pouca capacidade livre para preencher. Se uma para enquanto a outra pode executar, o compartilhamento é útil. As GPUs aplicam a ocultação de latência em escala maior, mantendo muitos grupos de threads prontos para seus escalonadores.

Principais conclusões

  • Threads de hardware duplicam o estado de execução enquanto compartilham os recursos de um núcleo.
  • A troca de granularidade fina ocorre a cada ciclo; a de granularidade grossa responde a paradas longas.
  • O SMT pode emitir instruções de threads diferentes durante um ciclo.
  • As contagens de processadores lógicos incluem contextos de threads de hardware.
  • A ocultação de latência precisa de trabalho pronto e pode ser limitada pela disputa por recursos.
  • Uma vazão maior não precisa reduzir o tempo de execução de uma thread individual.
2

Estime a aceleração paralela útil

Processadores extras dividem apenas o trabalho que pode ser executado em paralelo e introduzem custos próprios. Comece pelo tempo decorrido e pela fração sequencial; depois, distinga concluir uma tarefa fixa mais cedo de resolver uma tarefa maior no mesmo tempo. O equilíbrio de carga e a coordenação explicam outras perdas. O modelo Roofline acrescenta outro limite: se a memória consegue alimentar as unidades aritméticas disponíveis com rapidez suficiente.

2.1 Calcule o ganho e seu limite

Uma máquina paralela é útil quando altera o tempo decorrido. A aceleração compara a melhor execução sequencial com a execução paralela; a eficiência compara esse ganho com o número de processadores usados.

Comece pelo tempo medido

Para p processadores, S(p)=T1/Tp e E(p)=S(p)/p. Uma tarefa sequencial de 100 s que termina em 16 s em oito núcleos tem aceleração 100/16=6,25. Sua eficiência é 6,25/8=0,78125, cerca de 78%. Meça o tempo decorrido de relógio para ambas as execuções, usando a mesma tarefa fixa.

Divida o tempo em partes melhorada e inalterada

Na lei de Amdahl, f é a fração do tempo de execução original que uma melhoria acelera. É uma fração de tempo, não uma fração das linhas de código-fonte. Se essa parte se torna s vezes mais rápida, então

Tnew=Told((1−f)+f/s),S=1(1−f)+f/s.

A parte inalterada ainda leva todo o seu tempo original. Para uma divisão paralela ideal entre p processadores, faça s=p. Esse modelo exclui sobrecargas de comunicação, desequilíbrio e sincronização; esses custos podem aumentar o tempo medido.

Com 90% de tempo paralelizável e dez processadores, o tempo normalizado é 0,1+0,9/10=0,19. A aceleração é 1/0,19≈5,26, e a eficiência é de cerca de 53%. Com 100 processadores, o tempo é 0,1+0,009=0,109 e a aceleração é de cerca de 9,17. Aumentar o número de processadores em dez vezes não dobrou a aceleração.

Encontre o limite antes de comprar mais processadores

À medida que o número de processadores cresce, o tempo paralelo se aproxima de zero. A fração sequencial permanece, produzindo o teto Smax=1/(1−f). Uma fração sequencial de 10% limita a aceleração ideal a 10; uma fração de 5% a limita a 20. Quantidades finitas de processadores se aproximam desses tetos por baixo.

A lei de Amdahl também avalia uma classe de instruções mais rápida. Se a multiplicação ocupa 30% de uma execução e se torna quatro vezes mais rápida, o tempo normalizado passa a ser 0,7+0,3/4=0,775. O programa inteiro fica apenas 1/0,775≈1,29 vezes mais rápido.

Resolva a partir de uma meta

Para obter aceleração 90 em 100 processadores, escreva 1/90=(1−f)+f/100=1−0,99f. Portanto, f=(1−1/90)/0,99≈0,99888. Apenas cerca de 0,11% do tempo original pode permanecer sequencial. Uma meta próxima do número de processadores exige uma fração inalterada muito pequena.

Uma aceleração medida pode às vezes superar o número de processadores. Dividir um grande conjunto de trabalho pode fazer cada parte caber na cache, reduzindo o custo por operação. Essa aceleração superlinear altera uma premissa do modelo simples: o trabalho paralelo já não é apenas o trabalho original dividido em parcelas iguais. Verifique o algoritmo, o tamanho dos dados e o comportamento da cache antes de interpretar essa medição.

Principais conclusões

  • A aceleração é o tempo sequencial dividido pelo tempo paralelo; a eficiência é a aceleração dividida pelo número de processadores.
  • A fração de Amdahl refere-se ao tempo de execução original.
  • Apenas a fração melhorada é dividida pelo fator de melhoria.
  • A fração sequencial determina o teto de aceleração para uma carga de trabalho fixa.
  • Efeitos de cache podem alterar o custo do trabalho e produzir aceleração medida superlinear.

2.2 Escale o problema e inclua os custos

Adicionar processadores pode reduzir o tempo da mesma tarefa ou permitir que uma máquina trate uma tarefa maior. A escalabilidade forte e a escalabilidade fraca medem esses usos diferentes, e ambas dependem de quanto trabalho útil resta após os custos de coordenação.

Trabalho fixo e trabalho crescente

A escalabilidade forte mantém o tamanho do problema fixo. A escalabilidade fraca aumenta o trabalho proporcionalmente ao número de processadores, mantendo constante o trabalho por processador. A escalabilidade fraca perfeita mantém o tempo decorrido constante enquanto o trabalho total cresce.

Considere dez adições sequenciais seguidas de uma soma elemento a elemento de duas matrizes. Uma matriz de 10 por 10 precisa de 100 adições paralelas. O tempo total é de 110 unidades em um processador, 20 em dez e 12 em cinquenta: acelerações de 5,5 e cerca de 9,2. Uma matriz de 40 por 40 precisa de 1.600 adições paralelas. Os tempos passam a 1.610, 170 e 42 unidades: acelerações de cerca de 9,5 e 38,3. O problema maior dá mais peso ao trabalho paralelo útil em relação às mesmas dez adições sequenciais.

A base diferente de Gustafson

A lei de Gustafson usa a fração do tempo sequencial medida na execução paralela. Chamando essa fração de s, a aceleração com tamanho escalonado é SG=s+(1−s)p. Para s=0,05 e 100 processadores, SG=0,05+0,95(100)=95,05.

A lei de Amdahl com 5% de tempo sequencial na execução original em um processador dá apenas cerca de 16,8 em 100 processadores. Essas frações usam denominadores diferentes e respondem a perguntas diferentes. Uma aceleração com tamanho escalonado de 95,05 não significa que a tarefa original de tamanho fixo terminou 95,05 vezes mais rápido.

A unidade mais lenta determina o tempo de conclusão

Se 400 unidades iguais de trabalho forem distribuídas entre oito núcleos, a parcela equilibrada será de 50 para cada um. Suponha que um receba 120 enquanto os outros sete recebem 40 cada. A etapa dura 120 unidades de tempo, portanto a aceleração é 400/120≈3,33. Dividir pela carga média deixaria de considerar a espera pelo núcleo mais ocupado.

Criação de threads, escalonamento, mensagens, barreiras e disputa pela largura de banda compartilhada também consomem tempo. Granularidade é a quantidade de cálculo entre eventos de comunicação ou sincronização. Partes maiores reduzem o custo de coordenação por operação útil, mas partes em número insuficiente podem deixar algumas unidades de trabalho ociosas.

Mais processadores podem aumentar o tempo

Para uma tarefa totalmente paralela de 100 s com sobrecarga de 0,5p segundos, Tp=100/p+0,5p. Dez processadores levam 15 s. Quatorze levam cerca de 14,14 s, perto do mínimo de aproximadamente 200 processadores. Quarenta levam 22,5 s porque sua sobrecarga de 20 s supera a redução do tempo de cálculo útil.

Ao apresentar um resultado, informe se o trabalho permaneceu fixo ou cresceu e compare com o tempo do melhor programa sequencial. Usar como base uma implementação paralela lenta executada em um processador pode inflar a aceleração apresentada.

Principais conclusões

  • A escalabilidade forte fixa o trabalho total; a fraca fixa o trabalho por processador.
  • A fração sequencial de Gustafson é medida na execução paralela.
  • A unidade de trabalho mais lenta determina o tempo de conclusão de uma etapa paralela.
  • Comunicação, sincronização e disputa por recursos podem crescer com o número de processadores.
  • A granularidade envolve um compromisso entre custo de coordenação e equilíbrio de carga.
  • Use o tempo decorrido e o melhor programa sequencial como base ao apresentar a aceleração.

2.3 Encontre o teto de cálculo ou de memória

A taxa aritmética anunciada de um processador é apenas um dos limites. O modelo Roofline também pergunta se a memória consegue fornecer dados com rapidez suficiente para sustentar essa taxa. Ele fornece um limite superior, que ajuda a identificar uma direção útil para a otimização.

Conte operações por byte da DRAM

A intensidade aritmética é o número de operações de ponto flutuante dividido pelos bytes transferidos entre a DRAM e o processador. O trabalho original sobre o modelo Roofline chama essa medida baseada na DRAM de intensidade operacional. Conte o tráfego nessa fronteira, incluindo leituras e escritas.

DAXPY calcula yi=axi+yi usando números de precisão dupla. Cada elemento exige uma multiplicação e uma adição: dois FLOPs. Ler um valor de 8 bytes de cada vetor e escrever 8 bytes de volta transfere 24 bytes. A intensidade é I=2/24≈0,0833 FLOPs por byte. O coeficiente escalar é reutilizado; nesse modelo de tráfego, ele não exige uma nova carga da DRAM para cada elemento.

Aplique os dois limites

Se a capacidade de cálculo de pico é P e a largura de banda de pico da memória é B, o teto é min⁡(P,BI). Largura de banda multiplicada por FLOPs por byte tem como unidade FLOPs por segundo. Em um gráfico log-log, o limite de largura de banda sobe em uma linha inclinada e o limite de cálculo é horizontal.

Para 1.000 GFLOP/s e 100 GB/s, o ponto de transição é P/B=1000/100=10 FLOPs por byte. Abaixo dessa intensidade, o teto de largura de banda é menor; acima dela, o teto de cálculo é menor. DAXPY é limitado a 100(2/24)≈8,33 GFLOP/s, menos de 1% da capacidade de cálculo de pico da máquina. Um kernel com intensidade 2 é limitado a 200 GFLOP/s.

Um kernel limitado pela largura de banda da memória ainda pode se beneficiar de núcleos extras ou de SIMD mais largo enquanto tiver poucas requisições em andamento para usar a largura de banda disponível. Quando essa largura de banda está saturada, a capacidade aritmética adicional não eleva seu teto. Aumentar a largura de banda ou realizar mais cálculo útil por byte transferido eleva esse limite.

A reutilização altera a intensidade

Multiplicar duas matrizes de precisão dupla de 1000 por 1000 realiza cerca de 2(1000)3=2×109 FLOPs. Se cada elemento das duas entradas e da saída atravessar a fronteira da DRAM uma vez, o tráfego total será de 24 MB, resultando em cerca de 83 FLOPs por byte. Esse valor está acima do ponto de transição da máquina do exemplo.

Uma implementação ingênua pode reler repetidamente os valores das matrizes da DRAM. A blocagem organiza os laços em torno de submatrizes que cabem na cache, de modo que os valores sirvam a muitas operações antes de serem substituídos. O algoritmo continua sendo a multiplicação de matrizes, mas a implementação transfere menos bytes da DRAM por operação.

Um teto não é um resultado medido

Um kernel pode ser executado abaixo do limite por causa de dependências, sobrecarga de instruções, padrões de acesso inadequados ou trabalho paralelo insuficiente. Tetos de desempenho mais baixos mostram essas restrições: a falta de SIMD pode reduzir o teto de cálculo, enquanto padrões de acesso inadequados reduzem a largura de banda utilizável. Um ponto abaixo de um teto precisa de investigação; o teto, por si só, não prevê sua taxa de execução exata.

Principais conclusões

  • A intensidade conta FLOPs por byte na fronteira da DRAM.
  • O teto é o menor valor entre a capacidade de cálculo de pico e a largura de banda multiplicada pela intensidade.
  • O ponto de transição é a capacidade de cálculo de pico dividida pela largura de banda de pico.
  • A reutilização pode aumentar a intensidade sem alterar o algoritmo matemático.
  • O modelo Roofline fornece um limite superior; tetos mais baixos explicam restrições adicionais.
3

Processe vetores com vias e threads de GPU

Vetores oferecem operações repetidas em elementos independentes, que podem ser distribuídas entre vias e threads. Acompanhe essa ideia desde registradores SIMD de largura fixa até laços vetoriais de comprimento variável e, depois, warps de GPU. Cada projeto precisa de uma organização eficaz dos dados e de trabalho suficiente para ocupar seu hardware. Um pequeno kernel mostra como índices de vetores se tornam índices de threads, enquanto os custos de transferência determinam se transferir o trabalho ajuda a tarefa completa.

3.1 Execute operações sobre vetores nas vias SIMD

Uma extensão SIMD divide um registrador largo em vias. Uma instrução realiza a mesma operação em cada via, tornando os laços regulares sobre elementos independentes uma boa opção.

Conte vias e iterações

O número de vias é igual à largura do registrador dividida pela largura do elemento. Um registrador de 256 bits comporta oito números de ponto flutuante de 32 bits, quatro de precisão dupla de 64 bits ou 32 elementos de um byte. SSE usa registradores XMM de 128 bits; AVX e AVX2 usam registradores YMM de 256 bits. No modo de 64 bits, há 16 registradores YMM. AVX-512 oferece 32 registradores ZMM de 512 bits, cada um comportando 16 números de ponto flutuante. Arm Neon usa registradores de 128 bits.

Para c[i] = a[i] + b[i] sobre 1.000 números de ponto flutuante, instruções de oito vias processam o vetor em 125 iterações vetoriais. Cada iteração carrega dois vetores, soma suas vias e armazena um vetor. Com 1.003 elementos, 125 iterações completas deixam três elementos. Um laço escalar para o restante ou uma operação com máscara trata essa parte curta sem acessar posições além dos vetores.

Oito vias representam capacidade aritmética, não uma garantia de aceleração de oito vezes do programa. A preparação, o tratamento do restante, o trabalho sequencial e a largura de banda da memória ainda consomem tempo.

Escolha uma organização que preencha um registrador

Cargas vetoriais simples funcionam bem com elementos contíguos, de passo unitário. Um vetor de pontos {x, y, z} com campos de 4 bytes coloca campos x consecutivos a 12 bytes de distância. Uma estrutura de vetores coloca os valores de x juntos, depois os valores de y e depois os de z. Processar apenas x agora pode preencher um vetor com uma carga contígua. Instruções de coleta e dispersão aceitam endereços espalhados, mas normalmente com custo de acesso maior.

Mantenha o trabalho condicional dentro das vias

Para c[i] = (a[i] > 0) ? a[i] : 0, uma comparação cria uma máscara por via. Uma seleção escolhe entre resultados candidatos, ou instruções com máscara atualizam apenas as vias selecionadas. As vias inativas mantêm ou recebem valores conforme o comportamento da máscara da instrução.

Se vias diferentes precisarem seguir ramos longos e diferentes, as instruções desses caminhos ainda deverão ser emitidas, com apenas as vias pertinentes ativas. O grupo não pode dar a cada via um fluxo de instruções separado. Uma máscara preserva a correção, mas não faz todas essas instruções de caminho desaparecerem.

Verifique a independência das iterações

Compiladores podem vetorizar laços automaticamente; programadores também podem usar bibliotecas ou funções intrínsecas como _mm256_add_ps. O compilador deve estabelecer que iterações simultâneas preservam o resultado. A recorrência a[i] = a[i-1] + b[i] depende do novo valor da iteração anterior e não pode ser vetorizada diretamente como elementos independentes. A possível sobreposição de ponteiros, chamada aliasing, também pode exigir uma verificação de sobreposição em tempo de execução ou impedir a vetorização.

Uma redução mantém várias somas parciais em um registrador e depois combina as vias. Reordenar adições de ponto flutuante pode alterar os últimos bits porque a adição não é associativa. Somas de inteiros coincidem quando a aritmética escolhida não apresenta estouro ou usa aritmética modular definida.

SIMD e execução em múltiplos núcleos podem ser combinados. Oito núcleos, cada um emitindo uma adição de oito vias por ciclo, podem realizar até 64 adições de ponto flutuante por ciclo. Eles ainda compartilham limites como a largura de banda da memória.

Principais conclusões

  • O número de vias SIMD depende tanto da largura do registrador quanto da largura do elemento.
  • Elementos restantes precisam de um trecho escalar ou de acesso com máscara correta.
  • Organizações contíguas ajudam cargas vetoriais a usar suas vias com eficiência.
  • Máscaras tratam condições por elemento enquanto compartilham a emissão de instruções.
  • Dependências e sobreposição de ponteiros podem impedir a vetorização direta.
  • Reduções de ponto flutuante podem alterar o arredondamento quando as operações são reagrupadas.

3.2 Deixe o comprimento do vetor controlar cada passagem do laço

Uma arquitetura vetorial expressa uma operação sobre uma sequência de elementos e armazena o comprimento do vetor ativo em um registrador. O mesmo programa pode ser executado em implementações com capacidades diferentes de registradores vetoriais.

Separe capacidade, comprimento e vias

A extensão vetorial RISC-V, RVV, versão 1.0, foi ratificada em 2021. Ela oferece 32 registradores vetoriais, de v0 a v31. Cada implementação escolhe a largura de seus registradores, VLEN, como uma potência de dois. A largura dos elementos e o agrupamento de registradores determinam quantos elementos cabem.

O comprimento ativo, vl, é o número de elementos tratados pelas próximas instruções vetoriais. vsetvli configura a operação vetorial a partir da quantidade restante de elementos e do formato desejado para eles, retornando o vl selecionado. O código avança pelo valor retornado. Isso importa porque o código portável deve usar o comprimento real selecionado pela implementação.

Vias são os pipelines paralelos que executam a operação vetorial. Uma adição de 32 elementos em quatro vias leva cerca de oito ciclos após o início do pipeline. Um vetor de 32 elementos não exige 32 unidades aritméticas. Vetores mais longos e mais vias são escolhas de projeto distintas.

Particione um laço em blocos

O particionamento do laço em blocos divide um laço longo em partes do tamanho de um vetor. Para 100 elementos e um máximo de 32 por operação, uma sequência válida de comprimentos é 32, 32, 32 e 4. Cada passagem carrega a próxima parte, calcula, armazena e reduz a quantidade restante pelo seu vl.

DAXPY sobre 1.000 números de precisão dupla pode, da mesma forma, usar 31 passagens de 32 seguidas por uma passagem de oito, totalizando 32 passagens. RVV pode escolher outros comprimentos válidos perto do fim, portanto o laço usa o vl retornado em vez de supor uma divisão final específica. Definir o comprimento ativo trata o trecho final curto sem um laço escalar separado para o restante.

O padrão de controle do laço é:

  1. Solicite um comprimento para os elementos restantes.
  2. Carregue e calcule essa quantidade de elementos.
  3. Armazene os resultados.
  4. Avance os ponteiros e subtraia o comprimento retornado.

Uma instrução vetorial descreve muitas operações sobre elementos, reduzindo o trabalho de busca e decodificação em comparação com um corpo escalar repetido para cada elemento.

Alimente operações dependentes e dados não contíguos

O encadeamento permite que uma instrução vetorial consumidora comece a usar os primeiros resultados antes que a produtora tenha terminado os elementos posteriores. Em uma multiplicação seguida de uma adição, o primeiro produto pode entrar no pipeline de adição enquanto os produtos posteriores ainda estão sendo formados.

Uma máscara, normalmente no registrador v0 de RVV, seleciona quais elementos são atualizados. Uma carga com passo constante acessa elementos com um espaçamento fixo em bytes. Em uma matriz de precisão dupla de 100 por 100 armazenada por linhas, descer uma coluna avança 100 elementos, ou 800 bytes. Cargas e armazenamentos indexados usam endereços explícitos para dados irregulares.

Arquiteturas vetoriais e extensões de largura fixa são ambas SIMD na taxonomia de Flynn. Extensões de largura fixa codificam larguras específicas; código RVV expressa comprimentos que se adaptam ao hardware disponível. Ambas ainda precisam de uma ordem de execução que respeite as dependências de dados do laço.

Principais conclusões

  • O comprimento do vetor indica quantos elementos uma operação trata; as vias indicam quantos podem avançar juntos.
  • O código RVV avança pelo comprimento real retornado por vsetvli.
  • O particionamento do laço em blocos processa um vetor longo em partes do tamanho de um vetor.
  • O encadeamento sobrepõe operações vetoriais dependentes elemento a elemento.
  • Máscaras, passos e acessos indexados permitem tratar dados menos regulares.

3.3 Mantenha uma GPU ocupada com muitos warps

Uma CPU concentra recursos em baixa latência para poucas threads. Uma GPU concentra recursos em alta vazão entre muitas threads com paralelismo de dados. Escolher entre elas exige analisar a tarefa inteira, incluindo a movimentação de dados.

Threads são executadas em multiprocessadores de streaming

Uma GPU da NVIDIA contém muitos multiprocessadores de streaming, ou SMs. Um SM tem vias aritméticas, escalonadores de warps, um grande banco de registradores e memória compartilhada rápida no chip. Um “núcleo CUDA” designa uma via aritmética, não um núcleo completo e independente semelhante ao de uma CPU. A AMD chama o grupo de processamento correspondente de unidade de computação.

A NVIDIA agrupa threads em warps de 32. Uma instrução emitida opera sobre as threads ativas do warp, cada uma com seus próprios valores de registradores e dados. Isso é SIMT, instrução única e múltiplas threads. A AMD usa wavefronts, com 32 ou 64 threads, dependendo da arquitetura.

Um SM mantém muitos warps residentes. Quando um espera pela memória, o escalonador seleciona outro warp pronto. Ter mais threads prontas do que vias oculta a latência; isso não reduz a latência de um acesso individual à DRAM.

A divergência deixa vias inativas

Se threads de um warp seguirem ramos diferentes, o warp executará os caminhos necessários com as outras threads desativadas por máscara. Um if-else dividido igualmente, com ramos de mesmo custo, pode levar aproximadamente o dobro do tempo de um caminho porque ambos precisam ser executados. Um desvio pode não causar prejuízo quando sua condição é uniforme dentro de cada warp, mesmo que warps diferentes escolham caminhos diferentes.

Faça os acessos à memória trabalharem em conjunto

Registradores por thread armazenam valores privados. A memória compartilhada por bloco é um armazenamento no chip gerenciado pelo programa. As caches L1 e L2 permitem reutilização automática, enquanto a memória global é a DRAM da GPU, como GDDR ou HBM.

Quando 32 threads leem palavras consecutivas de 4 bytes, seu intervalo de 128 bytes pode ser atendido por um pequeno número de transações largas. Essa coalescência usa a largura de banda com eficiência. Endereços espalhados podem exigir muitas transações para os mesmos dados úteis. A reutilização na memória compartilhada pode reduzir ainda mais o tráfego repetido da memória global.

Inclua o tempo de transferência

Para uma GPU dedicada, entradas e resultados atravessam um enlace como PCIe ou NVLink. Enviar 800 MB e receber 400 MB a uma taxa efetiva de 20 GB/s transfere 1,2 GB em 0,06 s, ou 60 ms. Acrescentar um kernel de 10 ms resulta em 70 ms no total. Uma CPU que termina em 50 ms vence essa comparação apesar do cálculo muito mais rápido da GPU.

Manter dados na GPU ao longo de vários kernels evita transferências repetidas. Tarefas grandes e regulares também podem oferecer trabalho aritmético útil suficiente para compensar os custos de movimentação e lançamento. Tarefas pequenas, sequenciais e com muitos desvios frequentemente favorecem uma CPU.

Especialize ainda mais quando o trabalho permitir

Um sistema heterogêneo usa a CPU para executar o programa e o sistema operacional e um acelerador para as partes adequadas. Aceleradores de domínio específico, como TPUs e NPUs, dedicam hardware a uma tarefa mais restrita, frequentemente multiplicação de matrizes com inteiros de 8 bits ou ponto flutuante de 16 bits. A especialização pode melhorar o desempenho por watt nesse domínio, ao mesmo tempo que reduz a variedade de trabalhos que o hardware trata bem.

Principais conclusões

  • Um SM escalona warps; um núcleo CUDA é uma via aritmética.
  • Warps da NVIDIA contêm 32 threads com dados separados e emissão de instruções compartilhada.
  • Warps residentes e prontos ocultam esperas pela memória.
  • Divergência e acessos espalhados desperdiçam tempo das vias e largura de banda da memória.
  • Decisões de transferir trabalho incluem as transferências e o tempo do kernel.
  • Aceleradores especializados trocam flexibilidade por eficiência em um domínio mais restrito.

3.4 Mapeie elementos de vetores para threads de GPU

Um kernel de GPU é executado uma vez por thread lançada. O hospedeiro lança uma grade de blocos de threads, e cada thread calcula qual parte dos dados lhe cabe. CUDA chama a CPU de hospedeiro e a GPU de dispositivo; OpenCL usa os termos relacionados work-item e work-group.

Calcule um índice único

Para um lançamento unidimensional, o índice do elemento é blockIdx.x * blockDim.x + threadIdx.x. Com 256 threads por bloco, a thread 5 no bloco 2 trata o elemento 517: os dois blocos anteriores correspondem a 512 elementos, e a thread acrescenta um deslocamento de cinco. Os índices de threads e blocos começam em zero.

Um kernel SAXPY aplica uma multiplicação e uma adição a cada número de ponto flutuante:

__global__ void saxpy(int n, float a, float *x, float *y) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) {
        y[i] = a * x[i] + y[i];
    }
}

A grade substitui o laço comum sobre os elementos. Cada thread ativa atualiza seu próprio y[i]; threads vizinhas usam endereços vizinhos, favorecendo a coalescência.

Arredonde o número de blocos para cima

Para 1.000.000 de elementos e 256 threads por bloco, a grade precisa de ⌈1000000/256⌉=3907 blocos. Eles lançam 1.000.192 threads. As últimas 192 têm índices fora do vetor, portanto a condição i < n impede seus acessos à memória. Arredondar para baixo lançaria threads insuficientes e deixaria elementos válidos sem tratamento.

Um bloco de 256 threads forma oito warps. Blocos podem ser atribuídos a qualquer SM e executados em qualquer ordem. A correção do programa não deve depender de o bloco 0 terminar antes do bloco 1.

Organize o trabalho do hospedeiro e do dispositivo

Um hospedeiro típico aloca armazenamento no dispositivo, copia as entradas, lança saxpy<<<3907, 256>>>(n, 2.0f, d_x, d_y) e obtém os resultados. O lançamento é assíncrono: a CPU pode continuar enquanto o kernel é executado. O hospedeiro deve esperar por meio de sincronização ou de uma cópia bloqueante adequada dos resultados antes de usar os dados concluídos.

Coopere dentro de um bloco

Threads de um bloco podem trocar valores pela memória compartilhada e se encontrar em __syncthreads(). Toda thread participante dessa barreira de todo o bloco deve alcançá-la. Colocar a barreira dentro de if (i < n) não é seguro quando apenas algumas threads satisfazem a condição.

Para uma redução de 1.024 valores na memória compartilhada, 512 threads somam pares, depois 256 combinam os resultados, depois 128 e assim por diante. Dez estágios de divisão pela metade deixam uma soma. Uma barreira entre estágios impede que uma thread consuma um resultado parcial antes que sua produtora o escreva.

Um lançamento comum não tem barreira que abranja toda a grade. Blocos separados podem escrever somas parciais e um segundo kernel pode combiná-las, ou operações atômicas adequadas podem atualizar um resultado global. Uma barreira de bloco, por si só, não pode coordenar blocos diferentes. Um laço com passo igual ao tamanho da grade é outro padrão de mapeamento: cada thread trata vários elementos, avançando pelo tamanho total da grade.

Principais conclusões

  • Calcule índices a partir do tamanho do bloco, do índice do bloco e do índice da thread.
  • Arredonde o número de blocos para cima e proteja acessos fora dos limites.
  • Lançamentos de kernel são assíncronos em relação ao hospedeiro.
  • A memória compartilhada e __syncthreads() permitem cooperação dentro de um bloco.
  • Blocos comuns são executados independentemente; combinar resultados de blocos exige outro mecanismo.
4

Compartilhe memória e acompanhe a posse de blocos de cache

Um espaço de endereçamento comum permite que threads troquem valores por operações comuns de memória. Caches privadas tornam essas operações rápidas, mas criam várias cópias que precisam de coordenação. Acompanhe uma redução desde o trabalho local até os resultados compartilhados e depois acompanhe as permissões que mantêm coerentes as cópias armazenadas em cache. O armazenamento do diretório e o falso compartilhamento relacionam esses mecanismos de correção ao custo de desempenho da disposição dos dados na memória.

4.1 Compartilhe um espaço de endereçamento e combine resultados parciais

Um multiprocessador de memória compartilhada oferece a seus processadores um espaço de endereçamento físico. As threads se comunicam com cargas e armazenamentos em variáveis compartilhadas, enquanto mantêm valores privados, como somas parciais locais.

Endereços compartilhados podem ter custos diferentes

Em UMA, acesso uniforme à memória, o tempo de acesso à memória é aproximadamente o mesmo a partir de qualquer processador. Em NUMA, acesso não uniforme à memória, um soquete acessa sua memória local mais rapidamente do que a memória de outro soquete. O espaço de endereçamento é compartilhado mesmo que a memória física seja distribuída.

Com 70% de acessos locais a 80 ns e 30% de acessos remotos a 140 ns, a média ponderada é 0,7(80)+0,3(140)=98 ns. Mover dados para perto de quem mais os usa reduz a parcela remota. Contar todo acesso como local subestimaria o tempo.

Uma organização comum de caches oferece a cada núcleo caches L1 privadas de instruções e dados, frequentemente uma L2 privada e uma cache compartilhada de último nível. Um anel ou uma malha conecta os núcleos e as caches. Memória compartilhada descreve o endereçamento; ela não exige que todos os núcleos usem uma cache comum.

Divida, calcule e reduza

Para somar 64.000 valores em 64 núcleos, cada núcleo trata 1.000 valores. As 64 somas parciais podem ser combinadas em uma árvore de redução. O número de somadores ativos cai pela metade em cada estágio: 32, 16, 8, 4, 2 e 1. Seis estágios combinam os resultados parciais.

Usar aproximadamente 1.000 etapas de adição local mais seis etapas de combinação resulta em cerca de 1.006 etapas no caminho mais longo, antes da sobrecarga. A árvore evita que cada entrada atualize um contador compartilhado. Cada estágio depende dos valores concluídos do estágio anterior, portanto as unidades de trabalho se encontram em barreiras entre estágios.

OpenMP pode expressar isso com #pragma omp parallel for reduction(+:sum). Ele divide as iterações, dá às threads somas parciais privadas e as combina. Threads POSIX oferecem controle mais explícito sobre o gerenciamento de threads.

Torne uma atualização indivisível

Uma operação de leitura-modificação-escrita atômica torna uma atualização indivisível do ponto de vista dos outros processadores. A troca atômica e a busca e soma atômica são exemplos. Uma carga seguida de um armazenamento comum são duas operações separadas, portanto outra thread pode intervir.

RISC-V oferece lr.w e sc.w. A carga reservada lê uma palavra e estabelece uma reserva. O armazenamento condicional tenta escrever e informa sucesso ou falha. Uma escrita intermediária na posição reservada faz a tentativa falhar; o software tenta novamente. A reserva não bloqueia outros processadores, e a falha também pode ocorrer por outros motivos permitidos. Essas operações primitivas dão suporte a mecanismos de sincronização.

Observe os gargalos compartilhados

Se cada núcleo consegue transferir continuamente 15 GB/s, mas o soquete fornece 60 GB/s, cerca de quatro desses fluxos saturam a largura de banda. Mais núcleos não podem aumentar a taxa de dados do soquete. A comunicação por caches também exige trabalho: quem escreve sem permissão de escrita deve obter a posse e invalidar outras cópias. Quem escreve e já possui um bloco no estado modificado pode continuar localmente; leitores posteriores podem precisar buscar uma nova cópia.

Principais conclusões

  • Memória compartilhada significa um espaço de endereçamento, com dados e caches privados ainda possíveis.
  • NUMA torna a localização dos dados parte do desempenho.
  • Somas parciais locais e uma árvore de redução limitam a disputa por recursos.
  • Barreiras separam fases dependentes do trabalho.
  • Operações atômicas protegem atualizações indivisíveis; LR/SC tenta novamente após tentativas malsucedidas.
  • Núcleos compartilham a largura de banda da memória e arcam com o custo das transferências de posse.

4.2 Mantenha coerentes as cópias de uma posição

Caches privadas melhoram a latência, mas podem manter várias cópias da mesma posição de memória. A coerência de cache impede que essas cópias apresentem históricos conflitantes das escritas nessa posição.

Por que atualizar a memória não basta

Comece com X = 0 na memória. O núcleo A lê e armazena zero em sua cache; o núcleo B faz o mesmo. A escreve um em sua cache com escrita posterior. Sem um protocolo de coerência, B pode acertar em sua própria cache e continuar lendo zero. Escrever diretamente na memória não corrigiria a cópia já armazenada na cache de B.

A coerência funciona na granularidade de blocos de cache, normalmente de 64 bytes. Um controlador rastreia o estado de cada bloco e segue as regras do protocolo quando processadores leem ou escrevem nele. A migração move dados úteis para a cache de quem os usa no momento. A replicação permite que vários leitores mantenham cópias limpas. A coerência deve preservar ambos os benefícios enquanto controla as escritas.

Três propriedades necessárias
PropriedadeO que exige
Ordem do programa para uma posiçãoUm processador lê sua própria escrita anterior se nenhuma escrita intermediária a substituir.
Propagação de escritasUma escrita acaba se tornando visível aos outros processadores.
Serialização de escritasTodos os processadores concordam com a ordem das escritas nessa posição.

Se uma posição recebe uma escrita de um seguida de uma escrita de dois, os leitores não podem discordar sobre qual escrita veio depois. Observar a escrita posterior e depois a anterior inverteria esse histórico. Uma nova escrita subsequente poderia, é claro, armazenar o valor um novamente; a serialização diz respeito a eventos de escrita, não à possibilidade de um valor numérico se repetir.

Controle a posse e as cópias

Em um protocolo de invalidação na escrita, quem escreve obtém permissão exclusiva de escrita e invalida outras cópias armazenadas em cache. Uma leitura posterior de um bloco invalidado sofre uma falta e busca os dados atuais. Essa é uma falta de coerência, além das faltas compulsórias, de capacidade e de conflito.

Um protocolo de atualização na escrita envia novos valores às cópias existentes. Escritas repetidas podem tornar isso custoso. A monitoração de coerência difunde requisições para que as caches possam reagir. Um diretório rastreia os detentores de cópias e direciona mensagens às caches pertinentes.

Coerência, ordenação e atomicidade

A coerência diz respeito a uma posição. Um modelo de consistência de memória define as ordenações observáveis permitidas e os resultados de leituras e escritas, incluindo operações em posições diferentes. A consistência sequencial exige um resultado que corresponda a um entrelaçamento que preserve a ordem do programa de cada processador. Modelos relaxados permitem mais reordenações; instruções de barreira de memória impõem a ordenação necessária quando preciso.

Nem cópias coerentes nem uma ordenação consistente tornam atômico um incremento de várias instruções. Suponha que duas threads incrementem um contador compartilhado inicialmente igual a cinco. Uma sequência possível é: A lê cinco, B lê cinco, A escreve seis, B escreve seis. Cada leitura e escrita pode ser coerente, mas o contador final é seis em vez de sete. O programa precisa de uma atualização atômica ou de sincronização adequada para preservar ambos os incrementos.

Principais conclusões

  • A coerência é necessária mesmo quando as caches escrevem diretamente na memória.
  • Sistemas coerentes preservam a ordem do programa para uma posição, propagam escritas e serializam escritas.
  • A invalidação na escrita remove outras cópias utilizáveis antes que um novo detentor escreva.
  • Dados invalidados podem causar faltas de coerência.
  • Modelos de consistência tratam da ordenação entre posições.
  • Uma leitura coerente e uma escrita coerente ainda formam duas operações separadas.

4.3 Acompanhe mudanças de posse em MSI e MESI

Um controlador de cache que monitora a coerência observa requisições em uma interconexão de difusão. Para acompanhar um protocolo, mantenha um estado para a cópia do bloco de cada núcleo e atualize todas as cópias afetadas após cada acesso.

Leia os estados como permissões
EstadoCópia utilizável?Quem mais pode possuí-la?A memória está atualizada?
Modificado (M)Sim, leituras e escritasNenhuma outra cópia válidaNão
Compartilhado (S)Sim, leiturasOutros leitores podem ter cópiasSim
Inválido (I)NãoOutras caches podem ter cópiasDepende do estado delas
Exclusivo (E), apenas MESISim, leituras e transição silenciosa para escritaNenhuma outra cópia válidaSim

No MSI básico, uma falta de leitura envia uma leitura ao barramento e carrega o bloco em S. Escrever em um bloco em S exige uma promoção para invalidar outras cópias. Escrever a partir de I exige uma requisição de leitura exclusiva para buscar os dados e obter a posse. Quem escreve termina em M. Um acerto em M não exige transação de coerência.

Acompanhe cinco acessos

Comece com X = 0 na memória e A e B no estado inválido.

  1. A lê X. Uma leitura no barramento fornece zero. Estados: A = S, B = I.
  2. B lê X. Outra leitura no barramento fornece zero. Estados: A = S, B = S.
  3. A escreve um. Sua promoção invalida B. Estados: A = M, B = I.
  4. B lê X. B sofre uma falta; A fornece um e passa a S. No MSI básico, a memória também é atualizada. Estados: A = S, B = S.
  5. B escreve dois. Sua promoção invalida A. Estados: A = I, B = M.

Cada acesso nesse acompanhamento exige uma transação no barramento. O quarto acesso é a verificação importante de posse: a memória ainda tinha o valor antigo antes de A fornecer seus dados modificados.

O que o estado exclusivo economiza

O MESI acrescenta E para uma única cópia limpa em cache. Se A lê um bloco que não está em cache e nenhuma outra cache o possui, A recebe E. Uma escrita posterior muda E para M silenciosamente, pois não há outras cópias a invalidar. O MSI carregaria primeiro em S e depois enviaria uma promoção para essa escrita.

Se outro núcleo lê enquanto A possui E, ambos passam a S. M e E têm um único detentor válido, mas apenas M contém dados mais recentes que a memória.

Escritas repetidas e escala

Quem escreve e obteve M pode atualizar o bloco dez vezes sem dez novas invalidações. Um esquema de atualização na escrita enviaria os valores alterados aos detentores de cópias.

A monitoração por difusão se torna custosa à medida que mais núcleos observam cada requisição. Estruturas de diretório reduzem essa distribuição. Protocolos mais elaborados acrescentam estados úteis: o estado Owned do MOESI permite uma cópia modificada compartilhada, e o MESIF designa um detentor Forward para responder às requisições.

Principais conclusões

  • MSI rastreia cópias nos estados modificado, compartilhado e inválido.
  • Quem escreve precisa de posse exclusiva; acertos no estado modificado permanecem locais.
  • Uma leitura remota faz o detentor no estado modificado fornecer dados atuais e passar a compartilhado no MSI básico.
  • O estado exclusivo do MESI permite que um único leitor com cópia limpa escreva sem uma transação de promoção.
  • Os estados exclusivo e modificado têm um único detentor, mas apenas o modificado contém dados alterados.

4.4 Rastreie detentores de cópias e separe dados independentes

Difundir cada requisição de coerência se torna custoso em máquinas grandes. Um diretório registra quais caches podem possuir cada bloco para que as requisições possam ser enviadas a essas caches. O mesmo rastreamento em nível de bloco também explica um problema comum de desempenho: o falso compartilhamento.

Consulte a origem de um bloco

Cada bloco tem uma entrada no diretório de origem que registra se ele não está em cache, está compartilhado ou modificado e quais caches o possuem. As origens são distribuídas entre nós ou partes do diretório, distribuindo o armazenamento e o tratamento de requisições.

Uma falta de leitura vai para a origem. Se a memória tiver os dados atuais, ela poderá fornecê-los e o diretório registrará o novo detentor de cópia. Se outra cache possuir uma cópia no estado modificado, a origem encaminhará a requisição a essa detentora para que os dados atuais sejam fornecidos. Em um protocolo básico de diretório, isso também atualiza a memória novamente.

Para escrever sem já ter a posse no estado modificado, um núcleo pede permissão à origem. O diretório envia invalidações aos detentores registrados, espera as confirmações e concede a posse exclusiva. Acertos de escrita repetidos em M não precisam de outras mensagens de coerência. A passagem pelo diretório acrescenta latência, mas o tráfego ponto a ponto evita consultar todas as caches sobre cada bloco. Filtros de monitoração no chip atendem a um objetivo relacionado, restringindo as requisições aos possíveis detentores.

Estime o armazenamento do diretório

Um vetor de presença completo tem um bit por núcleo por bloco. Para 64 núcleos, são 64 bits, ou oito bytes. Em relação a um bloco de dados de 64 bytes, apenas os bits de presença custam 8/64=0,125, ou 12,5%. Com 256 núcleos, o vetor de 32 bytes custa 50%. Bits de estado acrescentam mais. Listas limitadas de detentores, vetores de granularidade mais grossa e o rastreamento apenas de blocos em cache reduzem esse custo de armazenamento.

Reconheça o falso compartilhamento

O compartilhamento verdadeiro ocorre quando núcleos trocam dados pela mesma palavra. O falso compartilhamento ocorre quando eles acessam variáveis diferentes dentro de um bloco de cache e pelo menos um escreve. As variáveis são independentes no programa, mas a unidade de coerência é maior que cada uma delas.

Duas threads incrementam contadores separados de 8 bytes em 0x1000 e 0x1008. Com blocos de 64 bytes, seus números de bloco são ⌊4096/64⌋=64 e ⌊4104/64⌋=64. Cada mudança de posse transfere a permissão para ambos os contadores em conjunto. Escritas alternadas frequentes podem fazer o bloco passar de uma cache para outra mesmo que nenhuma thread precise do valor da outra.

Mover o segundo contador para 0x1040 o coloca no bloco 65. Preenchimento ou alinhamento pode separar dados de cada thread; agrupar valores por quem os escreve também ajuda. Um acumulador local escrito de volta uma vez reduz o tráfego de posse sem acrescentar preenchimento a cada valor.

Quem escreve e quem lê uma variável vizinha também podem sofrer falso compartilhamento: quem escreve invalida o bloco que, de outra forma, seria útil ao leitor. Dois leitores sozinhos não o causam. O falso compartilhamento acrescenta tráfego e atraso; ele não faz, por si só, que atualizações de variáveis separadas produzam valores incorretos. Meça os padrões de acesso e a posição das linhas de cache antes de alterar uma organização de dados.

Principais conclusões

  • Diretórios enviam mensagens de coerência aos detentores registrados por meio da origem de um bloco.
  • O armazenamento de vetores de presença cresce com o número de núcleos e de blocos.
  • O falso compartilhamento envolve variáveis diferentes em um bloco e pelo menos uma escrita.
  • Separe a posse com preenchimento, posicionamento ou menos escritas compartilhadas.
5

Conecte nós e opere em escala de centro de dados

Além de uma máquina de memória compartilhada, os nós trocam mensagens por uma rede. Um aglomerado de computadores deve posicionar dados e organizar a comunicação com o mesmo cuidado com que divide os cálculos. Em escala de centro de dados, a rede funciona junto com a alimentação elétrica, a refrigeração e as falhas rotineiras de hardware. Compare a capacidade da rede com um corte crítico e depois use cálculos de energia e latência para avaliar como um grande conjunto de servidores fornece um serviço confiável.

5.1 Compare nós de memória privada e suas redes

Um aglomerado de computadores conecta computadores completos, cada um com sua própria memória e sistema operacional. Os nós cooperam por mensagens explícitas. A localização dos dados e o custo de comunicação, portanto, passam a fazer parte do modelo de desempenho do programa.

Particione dados e combine resultados

MPI, a interface de passagem de mensagens, dá a cada processo um identificador no comunicador e operações como envio, recebimento, difusão e redução. Um programa SPMD pode usar esses identificadores para selecionar os dados de cada processo. Um ponteiro no espaço de endereçamento privado de um nó não é uma referência comum de memória compartilhada aos dados de outro nó.

Se um milhão de valores já estiverem distribuídos por 100 nós, cada nó somará 10.000 localmente. Uma redução em árvore combina as somas parciais em sete rodadas porque ⌈log⁡2100⌉=7. Essas rodadas envolvem mensagens de rede, não apenas adições locais. Manter os dados perto do trabalho que os usa reduz as transferências.

Aglomerados podem crescer com componentes padronizados, e o hardware com falha pode ser substituído. Uma aplicação ainda pode precisar de recuperação ou reinício após a falha de um nó; nós substituíveis, por si só, não preservam o progresso de uma tarefa interrompida.

Meça mais que a velocidade do enlace

Latência é o tempo que uma mensagem leva para chegar. Largura de banda do enlace é a taxa de dados de um enlace. A largura de banda total da rede soma a capacidade dos enlaces e descreve um agregado ideal com todos os enlaces ocupados. A largura de banda de bisseção soma a capacidade que atravessa o corte de menor capacidade que divide os nós em metades iguais.

Para enlaces de mesma capacidade e largura de banda B, compare redes de 64 nós usando uma convenção consistente de contagem de enlaces:

TopologiaEnlacesCapacidade totalCapacidade de bisseção
Anel6464B2B
Malha de 8 por 8112112B8B
Toro de 8 por 8128128B16B
Hipercubo de 6 dimensões192192B32B
Totalmente conectada20162016B1024B

A malha tem oito linhas de sete enlaces horizontais e oito colunas de sete enlaces verticais, totalizando 112. Conectar as extremidades das duas dimensões produz os 128 enlaces do toro. Cada nó do hipercubo tem seis vizinhos, resultando em 64(6)/2=192 enlaces porque cada enlace é contado em duas extremidades.

Acompanhe o corte e depois considere o custo

Um corte que divide um anel em duas metades atravessa apenas dois enlaces. Muitas mensagens podem, portanto, disputar esse limite apesar dos 64 enlaces do anel no total. Uma rede totalmente conectada tem 32(32)=1024 enlaces entre suas duas metades, mas precisa de 64(63)/2=2016 enlaces no total.

Mais enlaces podem melhorar a largura de banda e reduzir saltos, ao mesmo tempo que aumentam o número de portas de comutadores, cabos e a potência necessária. Barramentos compartilhados têm um único recurso de comunicação compartilhado; malhas e toros distribuem os enlaces pelo espaço. Grandes aglomerados frequentemente usam redes comutadas de múltiplos estágios, como árvores gordas. Sua utilidade depende do padrão de tráfego e da capacidade agregada. Para comunicação entre metades de uma máquina, a bisseção revela um limite que o total oculta.

Principais conclusões

  • Nós de aglomerados usam espaços de endereçamento privados e comunicação explícita.
  • Identificadores MPI identificam processos; operações coletivas combinam trabalho distribuído.
  • Rodadas de mensagens acrescentam custo além da aritmética local.
  • A largura de banda total mede a capacidade agregada dos enlaces; a bisseção mede um corte crítico na máquina.
  • A capacidade da rede envolve compromissos com portas, cabos, potência e saltos.

5.2 Meça um centro de dados como um computador

Um computador em escala de centro de dados combina dezenas de milhares de servidores com alimentação elétrica, refrigeração e uma rede para fornecer serviços de internet. Requisições independentes fornecem trabalho paralelo, enquanto estruturas de processamento em lote, como MapReduce, dividem grandes tarefas de processamento de dados entre máquinas.

Ajuste o projeto ao serviço

Sistemas em escala de centro de dados priorizam custo por requisição, eficiência energética e disponibilidade. O software tenta novamente o trabalho, replica dados e desvia das máquinas com falha. Um supercomputador prioriza mais frequentemente um único programa científico fortemente acoplado e uma interconexão rápida.

Os servidores se conectam a comutadores no topo dos racks, que se conectam por níveis superiores de comutadores. Níveis adicionais aumentam a latência de comunicação. Os enlaces de subida frequentemente são sobressubscritos, ou seja, sua capacidade é inferior à capacidade agregada dos enlaces dos servidores. Algumas redes não bloqueantes no estilo Clos oferecem capacidade suficiente nos níveis superiores para evitar essa restrição.

Quarenta servidores com enlaces de 10 Gbit/s oferecem 400 Gbit/s a um comutador de rack. Quatro enlaces de subida de 25 Gbit/s fornecem 100 Gbit/s, portanto a proporção é 4:1. Se todos os servidores enviarem dados para fora do rack ao mesmo tempo e dividirem a capacidade igualmente, cada um terá uma média de 2,5 Gbit/s. Um servidor com pouca carga pode usar mais quando os outros estão ociosos.

Separe a sobrecarga da instalação do cálculo útil

A efetividade do uso de energia, PUE, é a energia total da instalação dividida pela energia dos equipamentos de TI no mesmo período. Dez MW de carga constante de TI mais 1,5 MW de sobrecarga de refrigeração e distribuição resultam em PUE=11,5/10=1,15. O valor ideal é 1,0. O Google informou uma PUE anual de 1,09 para o conjunto de suas instalações em 2025.

A PUE mede a sobrecarga da instalação, não os cálculos úteis por joule. Servidores ociosos ou ineficientes podem desperdiçar energia dentro da parcela de TI mesmo quando a instalação tem uma PUE excelente.

Para 50.000 servidores com média de 300 W, a potência de TI é de 15 MW. Com PUE de 1,2, a potência da instalação é de 18 MW. Mantida por 8.760 horas, ela consome 157.680 MWh; apenas a sobrecarga consome 26.280 MWh. Equipamentos de alimentação elétrica, refrigeração, eletricidade, servidores e edifícios contribuem para o custo de propriedade.

Uma carga baixa ainda pode consumir bastante potência

Proporcionalidade energética significa que a potência deve crescer proporcionalmente à carga. Um servidor com potência ociosa de 150 W e pico de 300 W, com crescimento linear, consome 150+0,3(150)=195 W com 30% de carga. Ele usa 65% da potência de pico para 30% do trabalho de pico. Medições históricas em centros de dados de grande escala encontraram muitos servidores operando entre aproximadamente 10% e 50% de utilização, tornando a potência ociosa importante.

Planeje para falhas e respostas lentas

Se 50.000 servidores apresentarem, cada um, uma média de uma falha a cada dez anos, espera-se que o conjunto apresente 5.000 falhas por ano, cerca de 14 por dia. Essa expectativa justifica redundância e novas tentativas; ela não prevê exatamente 14 falhas todos os dias.

Uma requisição que precisa de respostas de muitos servidores espera pela resposta necessária mais lenta. Se cada um de 100 servidores tiver, independentemente, uma chance de 1% de estar lento, a chance de nenhum estar lento é 0,99100. Assim, pelo menos um está lento com probabilidade 1−0,99100≈0,634. A latência de cauda de um servidor se torna um atraso comum em nível de requisição quando a distribuição entre servidores é grande.

Principais conclusões

  • O projeto em escala de centro de dados equilibra vazão do serviço, energia, custo e disponibilidade.
  • Enlaces de subida sobressubscritos limitam o tráfego simultâneo para fora do rack.
  • A PUE mede a sobrecarga da instalação, enquanto a eficiência dos servidores mede o trabalho útil dentro da parcela de TI.
  • A potência ociosa torna a baixa utilização custosa.
  • Grandes conjuntos de servidores apresentam falhas rotineiras, e a distribuição de requisições amplifica a latência de cauda.

Exercícios resolvidos de Processadores paralelos

5 Lições Interativas

1

Escolha uma fonte útil de trabalho paralelo

15 passos
Acompanhe uma carga de trabalho desde os limites de potência até os fluxos de instruções e depois use threads prontas para cobrir esperas pela memória.
  1. 1
    IntroduçãoMais trabalho sem aquecer mais o clock

    Um serviço precisa tratar mais tarefas, mas aumentar o clock da CPU excederia seu limite de potência. O hardware paralelo realiza mais trabalho dentro de um limite de potência fixo. Os projetistas podem acrescentar núcleos (MIMD), ampliar operações sobre dados (SIMD) ou manter mais threads prontas (multithreading). Cada escolha precisa de uma fonte adequada de trabalho. Comece identificando o que pode ser executado em conjunto e depois pergunte como esse trabalho chega ao hardware e se o benefício é um tempo de resposta menor ou maior capacidade de atendimento (vazão).

  2. 2
    ExplicaçãoA tensão tem efeito quadrático

    A potência dinâmica segue aproximadamente P≈CV2f. Com a capacitância inalterada, reduzir a tensão e a frequência para 85% multiplica a potência por 0,85×0,85×0,85=0,614125. Essa grande redução ajuda a explicar por que vários núcleos modestos podem ser atraentes. A barreira de potência surgiu quando reduções de tensão já não conseguiam compensar o custo em calor e potência de elevar as frequências de clock.

  3. 3
    ExemploSepare uma requisição de muitas requisições

    Se quatro downloads independentes forem executados em quatro núcleos, a máquina poderá concluir mais downloads por segundo mesmo que cada download leve o mesmo tempo. Isso é um ganho de vazão decorrente de trabalho em nível de requisição. Se uma imagem for dividida em regiões independentes e quatro threads as processarem, essa imagem poderá terminar mais cedo. O hardware paralelo atende aos dois objetivos, mas o programa deve disponibilizar o trabalho adequado.

  4. 4
    ExplicaçãoEncontre trabalho dentro de um programa

    Um pipeline sobrepõe instruções de um fluxo: ILP. Uma operação sobre vetores se repete entre elementos: DLP. Threads separadas fornecem TLP, com seus próprios estados de execução e um espaço de endereçamento de processo compartilhado. Essas formas podem coexistir. Um programa com threads que opera sobre vetores pode dividir regiões entre núcleos, usar SIMD dentro de cada região e executar essas instruções pelo pipeline de cada núcleo.

  5. 5
    DesafioAlternar conta?

    Um núcleo alterna entre duas tarefas. Ambas estão em andamento durante um segundo, mas suas instruções nunca são executadas no mesmo instante. Isso é execução paralela?

    ---reveal---

    É execução concorrente por compartilhamento de tempo. O paralelismo exige operações simultâneas em recursos de hardware distintos. Outro núcleo poderia oferecer essa simultaneidade, mas ainda precisaria de trabalho pronto para executar.

  6. 6
    ExplicaçãoPergunte quem escolhe a próxima instrução

    A taxonomia de Flynn começa pelos fluxos de instruções e de dados. Um núcleo escalar convencional é SISD. Uma operação larga que aplica uma instrução a vários elementos é SIMD. Processadores controlados independentemente que tratam seus dados são MIMD. MISD combina múltiplos fluxos de instruções com um fluxo de dados e tem poucos exemplos práticos inequívocos. Conte os fluxos em um nível de hardware escolhido.

  7. 7
    ExemploUm programa, progresso separado

    Quatro unidades de trabalho usam seus identificadores para dividir um vetor de 4.000 elementos em quatro regiões de 1.000 elementos. Elas executam o mesmo programa, mas uma pode chegar à sua adição final enquanto outra ainda carrega valores. Isso é software SPMD em hardware MIMD. Compartilhar o texto do programa não exige emissão de instruções em conjunto. Uma instrução SIMD dentro de qualquer unidade acrescentaria outro nível de execução paralela.

  8. 8
    DesafioClassifique o nível escolhido

    Uma CPU de múltiplos núcleos controlados independentemente usa adições vetoriais dentro de cada núcleo. Quais são as classes entre os núcleos e dentro de uma adição vetorial?

    ---reveal---

    Os núcleos formam hardware MIMD porque escolhem instruções independentemente. Cada adição vetorial é SIMD porque uma instrução opera sobre vários elementos de dados. Uma única máquina pode ter ambas as descrições quando elas se referem a níveis diferentes.

  9. 9
    ExplicaçãoMantenha o estado de execução pronto

    Um contexto de thread de hardware armazena um contador de programa e registradores. Vários contextos podem compartilhar as unidades aritméticas e as caches de um núcleo. Quando uma requisição de memória para uma thread, outra thread pronta pode preencher a capacidade de execução ociosa. O sistema operacional vê cada contexto como um processador lógico. Dois contextos em um núcleo ainda compartilham os recursos físicos de execução desse núcleo.

  10. 10
    ExplicaçãoEscolha quando as threads compartilham o núcleo

    O multithreading de granularidade fina seleciona uma thread pronta a cada ciclo. O de granularidade grossa troca após uma parada longa, arcando com os custos de troca e de preenchimento do pipeline. O SMT vai além em um núcleo de emissão múltipla: instruções de threads diferentes podem ser emitidas durante o mesmo ciclo. Os três dependem de trabalho útil pronto; nenhum fornece capacidade aritmética adicional ilimitada.

  11. 11
    ExemploPrimeiro meça o intervalo ocioso

    Uma thread calcula por 20 ciclos e depois espera 200. Seu período é de 220 ciclos, portanto o tempo ativo é 20/220≈9,1%. Uma espera longa deixa a maioria dos ciclos sem uso quando nenhuma outra thread está disponível. Mantenha o período completo de cálculo mais espera no denominador. Dividir apenas pela espera descreveria outra razão, não a fração de ciclos decorridos realizando trabalho útil.

  12. 12
    ExemploPreencha o intervalo com períodos de trabalho prontos

    Com quatro threads escalonadas livremente, cada uma contribuindo com 20 ciclos de cálculo por período de 220 ciclos, a utilização ideal é 80/220≈36,4%. Onze threads podem preencher o período: enquanto uma espera 200 ciclos, as outras dez contribuem com 200 ciclos de cálculo. Esse modelo ideal tem troca sem custo e nenhuma disputa adicional; a competição real por largura de banda e cache pode deixar menos trabalho útil pronto.

  13. 13
    DesafioOutro contexto resolveria?

    As unidades aritméticas de um núcleo já estão totalmente ocupadas, e suas duas threads precisam dessas mesmas unidades. Acrescentar outra thread de hardware forneceria a capacidade de outro núcleo? Explique usando o recurso que elas compartilham.

    ---reveal---

    Não. Um novo contexto fornece outro fluxo de instruções, mas ainda compartilha as unidades de execução ocupadas. Outro núcleo completo acrescenta hardware de execução. O multithreading é mais útil quando preenche capacidade que paradas ou um número limitado de instruções prontas deixam sem uso.

  14. 14
    ConexãoRelacione a melhoria do serviço à sua causa

    O serviço acrescenta contextos de hardware e agora conclui mais requisições independentes por segundo, enquanto o trabalho de CPU de cada requisição leva um pouco mais de tempo. Esse resultado é compatível com uma melhora de vazão: requisições prontas preenchem posições ociosas enquanto compartilham recursos. Seria enganoso chamá-lo de melhora na latência de uma única requisição. Escolha uma medida de desempenho que corresponda ao trabalho que os usuários precisam concluir.

  15. 15
    RecapitulaçãoTome a primeira decisão de hardware

    Para uma nova carga de trabalho, primeiro identifique instruções, elementos de dados, threads ou requisições independentes. Depois, localize o nível de hardware que controla seus fluxos de instruções. Se o ganho proposto vier de contextos extras, examine quais paradas deixam capacidade disponível e quais recursos os contextos compartilham. Isso fornece uma base concreta para escolher mais núcleos, operações mais largas ou mais threads prontas antes de medir o resultado.

2

Encontre o limite antes de acrescentar processadores

16 passos
Analise a aceleração de tamanho fixo, cargas de trabalho escalonadas e um kernel limitado pela largura de banda.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoTrês razões pelas quais hardware extra pode decepcionar
  2. 2
    ExplicaçãoEscolha a referência de tempo
  3. 3
    ExemploDivida apenas a parte paralela
  4. 4
    Ideia-chaveA parte fixa determina o limite total
  5. 5
    DesafioA meta de aceleração é possível?
  6. 6
    ExplicaçãoMantenha visível a questão da carga de trabalho
  7. 7
    ExemploUse a fração da execução paralela
  8. 8
    ExemploEspere pela unidade de trabalho mais ocupada
  9. 9
    DesafioQuando acrescentar núcleos aumenta o tempo?
  10. 10
    ExplicaçãoConte os bytes que saem da memória
  11. 11
    ExemploConstrua os dois tetos
  12. 12
    ExplicaçãoA reutilização desloca o kernel para a direita
  13. 13
    DesafioQual melhoria eleva o limite atual?
  14. 14
    DesafioUm kernel rápido dentro de um programa lento
  15. 15
    DicaTorne o ganho apresentado reproduzível
  16. 16
    RecapitulaçãoEscolha a próxima medição
3

Transforme um laço sobre vetor em trabalho para GPU

22 passos
Conte elementos SIMD, particione um laço vetorial em blocos e construa um mapeamento para GPU com verificação de limites e cooperação correta.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoComece com elementos independentes de um vetor
  2. 2
    ExemploConte elementos antes de instruções
  3. 3
    ExplicaçãoColoque os valores lado a lado
  4. 4
    ExplicaçãoSelecione elementos com uma máscara
  5. 5
    DesafioTodas as iterações podem começar juntas?
  6. 6
    ExplicaçãoDeixe o comprimento ativo descrever a passagem
  7. 7
    ExemploDivida um vetor longo em passagens
  8. 8
    ConexãoAlimente uma operação vetorial com outra
  9. 9
    DesafioAvance pelo que realmente foi executado
  10. 10
    ExplicaçãoEscalone um warp enquanto outro espera
  11. 11
    ExemploCaminhos diferentes desperdiçam vias ativas
  12. 12
    ExplicaçãoFaça uma transação atender muitas threads
  13. 13
    DesafioInclua o percurso até o dispositivo
  14. 14
    ConexãoEspecialize para uma carga de trabalho mais restrita
  15. 15
    ExemploEncontre o elemento do vetor de uma thread
  16. 16
    ExemploCubra o último bloco parcial
  17. 17
    ExplicaçãoEspere antes de o hospedeiro usar os resultados
  18. 18
    ExemploFaça uma redução dentro de um bloco
  19. 19
    DesafioUm bloco pode esperar por todos os outros?
  20. 20
    Ideia-chaveUma redução altera a ordem aritmética
  21. 21
    DesafioCombine um mapeamento seguro com acesso eficiente
  22. 22
    RecapitulaçãoVerifique o caminho completo do vetor
4

Acompanhe um bloco compartilhado do leitor ao escritor

19 passos
Divida uma soma, acompanhe permissões de cache e diagnostique interferência entre contadores independentes.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoVariáveis compartilhadas ainda precisam de coordenação
  2. 2
    ExplicaçãoUm espaço de endereçamento, caminhos de acesso diferentes
  3. 3
    ExemploConclua o trabalho local antes de combinar
  4. 4
    DesafioO que acontece após uma escrita intermediária?
  5. 5
    ExemploEncontre o acerto em cache desatualizado
  6. 6
    ExplicaçãoConcorde sobre o histórico de uma posição
  7. 7
    DesafioA coerência pode preservar ambos os incrementos?
  8. 8
    ConexãoMantenha ordenação separada de posse
  9. 9
    ExplicaçãoLeia as permissões no MSI
  10. 10
    ExemploPrimeiro dê cópias limpas aos dois núcleos
  11. 11
    ExemploTransfira a posse para quem escreve
  12. 12
    Ideia-chaveO estado exclusivo elimina uma requisição para dados privados
  13. 13
    DesafioAcompanhe uma leitura e duas escritas
  14. 14
    ExplicaçãoEnvie a requisição pela origem
  15. 15
    ExemploConverta bits antes de medir a sobrecarga
  16. 16
    ExemploDescubra quais bytes compartilham a posse
  17. 17
    DesafioQuem lê a variável vizinha precisa escrever?
  18. 18
    DesafioReduza a disputa em uma soma correta
  19. 19
    RecapitulaçãoExamine o programa e o bloco
5

Acompanhe dados, energia e respostas lentas em um conjunto de servidores

14 passos
Compare cortes de rede, calcule a energia da instalação e veja por que serviços grandes se preparam para eventos raros.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoUm nó agora é um computador completo
  2. 2
    ExplicaçãoColoque o trabalho perto de sua entrada
  3. 3
    ExemploCombine somas parciais em rodadas de mensagens
  4. 4
    ExplicaçãoConte o corte estreito
  5. 5
    DesafioPague por uma rede mais larga
  6. 6
    ExplicaçãoCompartilhe os enlaces de subida
  7. 7
    ExemploInclua refrigeração e distribuição
  8. 8
    ExemploTransforme potência constante em energia anual
  9. 9
    DesafioQual eficiência a mudança melhorou?
  10. 10
    ExemploUma carga baixa ainda consome potência
  11. 11
    ExplicaçãoPequenas taxas de falha se somam no conjunto
  12. 12
    ExemploUma resposta lenta pode atrasar a requisição
  13. 13
    DesafioMais servidores reduzirão o tempo de toda requisição?
  14. 14
    RecapitulaçãoEscolha uma métrica para o conjunto com um objetivo

Questões de Processadores paralelos

50 Questões de Prática em 5 conjuntos

Conjunto 1: Reconheça o trabalho paralelo e seus custos10 Questões de Prática

Questão 1 de 10

Um serviço web atribui requisições independentes de download de imagens a servidores diferentes. Que tipo de paralelismo está sendo usado?
  1. Paralelismo em nível de instrução
  2. Paralelismo em nível de requisição
  3. Paralelismo em nível de dados
  4. Multithreading de granularidade fina
Mostrar respostaOcultar resposta
Resposta: B
Cada servidor trata uma requisição separada, portanto o trabalho paralelo vem de tarefas independentes. O paralelismo em nível de dados aplicaria a mesma operação a muitos elementos dentro de um cálculo; atender requisições diferentes não exige que elas avancem por uma instrução compartilhada.

Questão 2 de 10

Todos os processadores concordam com a ordem das escritas em uma posição de memória. Que propriedade de coerência é essa?
  1. Propagação de escritas
  2. Consistência sequencial
  3. Leitura-modificação-escrita atômica
  4. Serialização de escritas
Mostrar respostaOcultar resposta
Resposta: D
A serialização de escritas dá a todos os processadores a mesma ordem para as escritas em uma posição. A consistência sequencial também restringe o entrelaçamento geral de operações em diferentes posições, preservando a ordem do programa de cada processador. A concordância apenas sobre o histórico de escritas de uma posição é uma propriedade mais restrita.

Questão 3 de 10

Uma tarefa leva 144 s na melhor implementação sequencial e 24 s em oito processadores. Qual é sua eficiência paralela?
  1. 75%
  2. 16,7%
  3. 60%
  4. 80%
Mostrar respostaOcultar resposta
Resposta: A
A aceleração é a razão entre os tempos, 144/24 = 6. A eficiência divide esse ganho pelos oito processadores, resultando em 6/8=0,75, ou 75%. Informar 16,7% usa o tempo paralelo dividido pelo tempo sequencial, o que mede a fração restante do tempo em vez da eficiência.

Questão 4 de 10

Um kernel tem intensidade de 3 FLOPs por byte em hardware com capacidade de cálculo de pico de 720 GFLOP/s e largura de banda da DRAM de 80 GB/s. Qual limite do modelo Roofline se aplica?
  1. 720 GFLOP/s
  2. 960 GFLOP/s
  3. 240 GFLOP/s
  4. 26,7 GFLOP/s
Mostrar respostaOcultar resposta
Resposta: C
O teto de largura de banda é 80×3=240 GFLOP/s, abaixo do teto de cálculo de 720 GFLOP/s. O menor teto determina o limite. Escolher apenas a capacidade de cálculo de pico pressupõe que os dados possam chegar rápido o suficiente para sustentá-la, mas esse kernel precisaria de muito mais bytes por segundo do que a memória fornece.

Questão 5 de 10

Quantos elementos de 64 bits cabem em um registrador SIMD de 512 bits?
  1. 4 elementos
  2. 16 elementos
  3. 8 elementos
  4. 64 elementos
Mostrar respostaOcultar resposta
Resposta: C
Divida a largura do registrador pela largura de um elemento: 512/64 = 8. O número de vias depende tanto do tamanho do elemento quanto do tamanho do registrador. Dezesseis vias comportariam valores de 32 bits, portanto usar essa contagem para valores de 64 bits reservaria apenas metade do espaço necessário por elemento.

Questão 6 de 10

Dois warps de GPU seguem caminhos opostos em um if-else. Dentro de cada warp, todas as threads concordam com o caminho. O que acontece com a divergência de desvios?
  1. Ambos os warps executam todos os ramos.
  2. Nenhum dos warps diverge internamente.
  3. Metade de cada warp fica inativa.
  4. Cada warp se divide em dois warps.
Mostrar respostaOcultar resposta
Resposta: B
A divergência é determinada dentro de um warp, onde a emissão de instruções é compartilhada. Cada warp descrito tem uma condição uniforme e pode executar apenas seu próprio caminho. Warps diferentes podem seguir caminhos diferentes sem obrigar qualquer um deles a executar ambos os ramos com metade de suas vias desativadas por máscara.

Questão 7 de 10

Uma carga de trabalho NUMA realiza 60% de seus acessos a 75 ns e o restante a 135 ns. Qual é a latência média de acesso?
  1. 99 ns
  2. 105 ns
  3. 81 ns
  4. 135 ns
Mostrar respostaOcultar resposta
Resposta: A
Pondere cada latência por sua parcela de acessos: 0,6×75+0,4×135=45+54=99 ns. Uma média não ponderada dá 105 ns, mas isso exigiria quantidades iguais de acessos locais e remotos. Aqui, os acessos locais mais rápidos ocorrem com maior frequência.

Questão 8 de 10

Duas threads leem um contador coerente com valor 9 e depois ambas armazenam 10 após um incremento comum. Que propriedade falta ao incremento?
  1. Propagação de escritas
  2. Serialização de escritas
  3. Replicação de cache
  4. Atomicidade
Mostrar respostaOcultar resposta
Resposta: D
O incremento consiste em uma leitura e uma escrita separada, portanto ambas as threads podem ler nove antes que qualquer uma armazene dez. A coerência pode serializar corretamente as duas escritas de dez e ainda perder um incremento. Uma leitura-modificação-escrita atômica torna cada atualização inteira indivisível para a outra thread.

Questão 9 de 10

No MSI básico, A e B começam no estado inválido para um bloco que contém 4. A lê, A escreve 7 e depois B lê. Quais são os estados finais de A/B e o valor lido por B?
  1. M/S, com B lendo 7
  2. S/S, com B lendo 7
  3. I/S, com B lendo 4
  4. S/S, com B lendo 4
Mostrar respostaOcultar resposta
Resposta: B
A primeiro carrega o bloco no estado compartilhado e depois obtém a posse no estado modificado para escrever sete. A leitura posterior de B faz A fornecer o valor modificado e passar ao estado compartilhado; B também recebe o estado compartilhado. Deixar A no estado modificado entraria em conflito com a regra do MSI básico de que um bloco modificado não tem outra cópia válida em cache.

Questão 10 de 10

Um anel de 20 nós tem largura de banda igual de 5 Gbit/s por enlace. Usando um valor de capacidade por enlace, qual é sua largura de banda de bisseção?
  1. 10 Gbit/s
  2. 100 Gbit/s
  3. 50 Gbit/s
  4. 5 Gbit/s
Mostrar respostaOcultar resposta
Resposta: A
O corte mínimo em metades iguais de um anel atravessa dois enlaces, portanto sua capacidade é 2×5=10 Gbit/s. O total de 100 Gbit/s conta todos os vinte enlaces e descreve a capacidade agregada. Essa capacidade não pode ser usada integralmente para transportar tráfego pelos dois enlaces que separam as metades.
Conjunto 2: Aplique regras de escalabilidade, indexação e coerência10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Um núcleo emite instruções de duas threads diferentes durante o mesmo ciclo. Que técnica de hardware isso descreve?
  1. Multithreading de granularidade grossa
  2. Multithreading de granularidade fina
  3. Multithreading simultâneo
  4. Compartilhamento de tempo do sistema operacional
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma tarefa fixa passa 20% de seu tempo sequencial em trabalho que não pode ser paralelizado. Com divisão ideal do restante entre quatro processadores, qual é a aceleração resultante?
  1. 2,5
  2. 3,2
  3. 4,0
  4. 5,0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma simulação passa de dois milhões de células em quatro processadores para quatro milhões de células em oito processadores, mantendo fixo o trabalho por célula. Que experimento de escalabilidade é esse?
  1. Escalabilidade forte
  2. Escalabilidade superlinear
  3. Escalabilidade com carga fixa
  4. Escalabilidade fraca
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Um laço RVV tem 90 elementos restantes. Sua implementação escolhe comprimentos ativos sucessivos de 32, 32 e 26. Quantos elementos o código deve avançar após sua segunda passagem?
  1. 26 elementos
  2. 32 elementos
  3. 64 elementos
  4. 90 elementos
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Um vetor tem 4.103 elementos. Um kernel trata um elemento por thread e usa 128 threads por bloco. Quantos blocos são necessários?
  1. 33 blocos
  2. 32 blocos
  3. 34 blocos
  4. 129 blocos
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Seis núcleos executam, cada um, uma cópia de um programa. Eles escolhem instruções independentemente e processam regiões diferentes de um vetor. Qual é a classe do hardware?
  1. SIMD
  2. SISD
  3. MISD
  4. MIMD
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Em MESI, A lê um bloco que não está em cache, escreve nele, escreve novamente e depois B o lê. Comece com ambas as cópias no estado inválido. Quantas requisições de coerência ao barramento ocorrem nessa sequência?
  1. 1 requisição
  2. 3 requisições
  3. 2 requisições
  4. 4 requisições
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um diretório completo usa um bit de presença por núcleo para cada bloco de dados de 128 bytes. Com 128 núcleos, qual é a sobrecarga de armazenamento apenas do vetor de presença?
  1. 1,56%
  2. 12,5%
  3. 16%
  4. 100%
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Quarenta e oito nós de um aglomerado já possuem parcelas iguais de 960.000 valores. Uma árvore binária combina uma soma local por nó. Quais são a quantidade de valores por nó e o número de rodadas de combinação?
  1. 20.000 valores e 48 rodadas
  2. 46.080.000 valores e 6 rodadas
  3. 20.000 valores e 5 rodadas
  4. 20.000 valores e 6 rodadas
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um rack tem 24 servidores com enlaces de 25 Gbit/s e seis enlaces de subida de 50 Gbit/s. Com divisão igual quando todos os servidores enviam dados para fora do rack ao mesmo tempo, quais são a razão de sobressubscrição e a taxa por servidor?
  1. 2:1 e 25 Gbit/s
  2. 4:1 e 6,25 Gbit/s
  3. 2:1 e 12,5 Gbit/s
  4. 1:2 e 50 Gbit/s
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 3: Diagnostique limites de desempenho no sistema10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

A capacitância permanece fixa enquanto a tensão cai para 90% e a frequência para 80% de seus valores originais. Que fração da potência dinâmica original permanece?
  1. 0,720
  2. 0,810
  3. 0,5832
  4. 0,648
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Um único núcleo superescalar segue um fluxo de instruções e sobrepõe instruções escalares independentes. Como ele é classificado na taxonomia de Flynn?
  1. SIMD
  2. SISD
  3. MIMD
  4. MISD
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Seis núcleos recebem inicialmente quantidades de tarefas de mesmo custo iguais a 35, 35, 35, 35, 35 e 65. Um escalonador move dez tarefas do núcleo mais ocupado para cada um dos outros cinco. Sem sobrecarga e com uma tarefa por unidade de tempo por núcleo, como muda a aceleração em relação à execução sequencial?
  1. De cerca de 3,69 para 5,33
  2. De cerca de 3,69 para 6,00
  3. De exatamente 6,00 para 5,33
  4. De exatamente 4,00 para 5,33
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Uma máquina tem pico de 960 GFLOP/s e 120 GB/s. Um kernel realiza 12 GFLOPs e transfere 3 GB da DRAM. A blocagem reduz o tráfego pela metade sem alterar o trabalho. O que acontece com o limite do modelo Roofline?
  1. Ele sobe de 480 para 1.920 GFLOP/s.
  2. Ele permanece fixo em 480 GFLOP/s.
  3. Ele sobe de 480 para 960 GFLOP/s.
  4. Ele sobe de 240 para 480 GFLOP/s.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Um laço calcula a[i] = a[i-1] + b[i] da esquerda para a direita. Por que o compilador não pode substituir diretamente iterações consecutivas por vias SIMD independentes?
  1. Cada iteração lê valores de dois vetores diferentes.
  2. Cada iteração precisa do novo resultado da iteração anterior.
  3. Cada iteração contém mais de uma entrada aritmética.
  4. Cada iteração armazena seu resultado em um vetor contíguo.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um laço RVV tem 50 números de precisão dupla restantes e capacidade 32. A implementação retorna vl = 28. O programador avança ambos os ponteiros em 32 elementos e subtrai 32 da quantidade restante. Qual é o primeiro intervalo de dados perdido?
  1. Índices originais de 0 a 27
  2. Índices originais de 32 a 49
  3. Índices originais de 24 a 27
  4. Índices originais de 28 a 31
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Em um sistema NUMA, por que dois acessos ao mesmo endereço compartilhado podem ter latências diferentes a partir de soquetes diferentes?
  1. O endereço pode ser local para um soquete e remoto para outro.
  2. Cada soquete deve atribuir um valor numérico diferente ao endereço.
  3. Cada soquete deve usar um espaço de endereçamento separado no nível da aplicação.
  4. O endereço deve ignorar todas as caches privadas da máquina.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Com blocos de 64 bytes, A escreve repetidamente em um contador de 8 bytes em 0x2040; B lê repetidamente um valor de estado independente de 8 bytes em 0x2078. Por que B pode sofrer faltas de coerência?
  1. As variáveis ocupam blocos adjacentes, então cada leitura busca ambos os blocos.
  2. Ambas as threads escrevem no mesmo contador, então um incremento se perde.
  3. Ambas as variáveis ocupam o bloco 129, e as escritas de A invalidam a cópia de B.
  4. O leitor precisa da posse no estado modificado antes de ler o estado.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma adição vetorial de 72 elementos é executada em seis vias. Ignorando a inicialização, quantos ciclos são necessários para as operações sobre os elementos?
  1. 6 ciclos
  2. 72 ciclos
  3. 12 ciclos
  4. 432 ciclos
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Equipamentos de TI consomem uma potência constante de 8 MW e a sobrecarga da instalação acrescenta 2 MW. Qual é a PUE?
  1. 1,25
  2. 0,25
  3. 0,80
  4. 4,00
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 4: Combine o comportamento do hardware com modelos de desempenho10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma máquina tem 12 núcleos e duas threads de hardware por núcleo. Quantos processadores lógicos são visíveis e quantos núcleos físicos existem?
  1. 24 processadores lógicos e 12 núcleos
  2. 24 processadores lógicos e 24 núcleos
  3. 12 processadores lógicos e 24 núcleos
  4. 12 processadores lógicos e 12 núcleos
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Um sistema de núcleo único alterna entre duas tarefas de longa duração, sem executar suas instruções no mesmo instante. Como sua execução deve ser descrita?
  1. Paralela, mas não concorrente
  2. Paralela e concorrente
  3. Concorrente, mas não paralela
  4. Nem paralela nem concorrente
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Um kernel de baixa intensidade já satura a largura de banda da DRAM e é executado em seu limite do modelo Roofline. A largura SIMD dobra enquanto a largura de banda e a intensidade permanecem fixas. Como muda seu limite no modelo Roofline?
  1. Ele dobra.
  2. Ele cai pela metade.
  3. Ele aumenta pela intensidade original.
  4. Ele permanece igual.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Um kernel de redução usa if (i < n) { load_into_shared(); __syncthreads(); combine(); }. Em seu último bloco, apenas algumas threads satisfazem a condição. Que correção estrutural torna segura a barreira de bloco?
  1. Remover a verificação de limites para que todas as threads do bloco carreguem um elemento do vetor.
  2. Permitir que todas as threads do bloco alcancem a barreira, com valores neutros para entradas inativas.
  3. Substituir a barreira de bloco por uma espera do hospedeiro após o lançamento do kernel.
  4. Colocar uma segunda barreira idêntica dentro do mesmo ramo condicional.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Uma CPU leva 36 ms por lote. Uma GPU dedicada precisa receber 500 MB, executar três kernels de 4 ms e depois enviar 100 MB de volta. As transferências atingem 15 GB/s, não podem se sobrepor ao cálculo e o custo de lançamento é desprezível. Qual caminho é mais rápido e por quanto tempo?
  1. A GPU é mais rápida por 24 ms.
  2. A CPU é mais rápida por 16 ms.
  3. A CPU é mais rápida por 4 ms.
  4. A GPU é mais rápida por 16 ms.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Trinta e dois núcleos dividem igualmente 32.000 valores. Cada thread começa em zero e soma os valores atribuídos a ela; depois, uma árvore binária combina as somas parciais. Cada adição custa uma unidade de tempo; cada estágio da árvore também tem uma barreira de duas unidades. Sem outros custos, qual é a aceleração em relação a uma soma sequencial que começa em zero?
  1. Cerca de 31,53
  2. Cerca de 31,84
  3. Cerca de 31,69
  4. Exatamente 32,00
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um núcleo usa uma cache com escrita direta. Outro núcleo já possui uma cópia limpa em cache do mesmo endereço. Por que ainda é necessário um mecanismo de coerência após a escrita do primeiro núcleo?
  1. A escrita direta impede o primeiro núcleo de atualizar a memória.
  2. Uma cópia limpa em cache nunca pode se tornar inválida.
  3. O segundo núcleo deve descartar todos os blocos de cache a cada leitura.
  4. Atualizar apenas a memória deixa a outra cópia em cache desatualizada.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Em MESI, A lê um bloco que não está em cache, B o lê, A escreve 3, A escreve 6 e B lê novamente. Quantas requisições ao barramento ocorrem e qual valor a leitura final de B obtém?
  1. 3 requisições, retornando 6
  2. 5 requisições, retornando 6
  3. 4 requisições, retornando 6
  4. 4 requisições, retornando 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Duas instalações têm a mesma PUE. Uma opera servidores em sua maioria ociosos; a outra conclui muito mais trabalho com sua energia de TI. O que a PUE igual estabelece?
  1. Seus cálculos úteis por joule são iguais.
  2. Suas quantidades totais de energia da instalação são iguais.
  3. Seus percentuais de utilização dos servidores são iguais.
  4. Suas razões entre energia da instalação e de TI são iguais.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Oito núcleos de CPU controlados independentemente executam, cada um, uma adição SIMD de oito vias em um ciclo. Como os dois níveis devem ser descritos?
  1. SIMD entre núcleos e SISD dentro de cada adição
  2. SISD entre núcleos e MIMD dentro de cada adição
  3. MIMD entre núcleos e SIMD dentro de cada adição
  4. MISD entre núcleos e SIMD dentro de cada adição
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 5: Aplique os modelos a novas decisões de projeto10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma execução ideal com carga de trabalho fixa alcança aceleração 4 em oito processadores. Seu trabalho sequencial torna-se então duas vezes mais rápido, mantendo o trabalho paralelo inalterado. Qual aceleração a nova execução em oito processadores alcança em relação à referência sequencial original?
  1. 4,0
  2. 5,6
  3. 4,67
  4. 8,0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

O projeto A tem quatro núcleos com dois contextos de hardware cada; o projeto B tem dois núcleos com oito contextos cada. Cada thread repete 15 ciclos de cálculo e depois 105 ciclos de espera. Cada núcleo pode realizar uma etapa de cálculo por ciclo. Com escalonamento ideal, troca sem custo e sem disputa pela memória, como se comparam suas vazões de cálculo em regime estável?
  1. A fornece o dobro da vazão de B.
  2. Ambos fornecem a mesma vazão.
  3. B fornece o dobro da vazão de A.
  4. B fornece quatro vezes a vazão de A.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma carga de trabalho fixa deve alcançar aceleração de pelo menos 12 em dezesseis processadores sob escalabilidade ideal de Amdahl. Qual é a maior fração sequencial permitida de seu tempo original?
  1. 1/45, cerca de 2,22%
  2. 1/12, cerca de 8,33%
  3. 1/16, cerca de 6,25%
  4. 1/15, cerca de 6,67%
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Uma tarefa totalmente divisível tem o modelo de tempo medido Tp=288/p+2p segundos. Você pode usar 8, 12, 16 ou 24 processadores. Qual escolha termina mais rápido?
  1. 8 processadores
  2. 16 processadores
  3. 24 processadores
  4. 12 processadores
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Um laço soma dois vetores de 1.237 números de ponto flutuante usando instruções SIMD de 256 bits. Vetores completos são processados primeiro, seguidos de um trecho escalar final. Quantas iterações completas e quantos elementos escalares são necessários?
  1. 155 iterações vetoriais e 3 elementos escalares
  2. 154 iterações vetoriais e 8 elementos escalares
  3. 153 iterações vetoriais e 5 elementos escalares
  4. 154 iterações vetoriais e 5 elementos escalares
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um anel de 16 nós e uma rede totalmente conectada de 16 nós usam enlaces de 10 Gbit/s. Com um valor de capacidade por enlace, qual é o ganho de capacidade de bisseção da conexão total e de quantos enlaces extras ela precisa?
  1. 32 vezes a capacidade, com 120 enlaces extras
  2. 32 vezes a capacidade, com 104 enlaces extras
  3. 8 vezes a capacidade, com 104 enlaces extras
  4. 7,5 vezes a capacidade, com 104 enlaces extras
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Que grupo de hardware contém 32 threads que compartilham a emissão de instruções no modelo de execução SIMT da NVIDIA?
  1. Um bloco de threads
  2. Um multiprocessador de streaming
  3. Um warp
  4. Um núcleo CUDA
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um kernel com verificação de limites que trata um elemento por thread lança 37 blocos de 64 threads para um vetor de 2.350 elementos. Quantas threads no último bloco acessam elementos válidos e qual é seu último índice de thread válido dentro desse bloco?
  1. 46 threads; último índice local 45
  2. 46 threads; último índice local 46
  3. 18 threads; último índice local 17
  4. 47 threads; último índice local 46
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma cache mantém um bloco no estado exclusivo em MESI. Seu processador escreve no bloco enquanto nenhum outro núcleo o acessa. Qual é o estado resultante e qual requisição de coerência ocorre?
  1. Modificado, sem requisição ao barramento
  2. Compartilhado, com leitura no barramento
  3. Modificado, com requisição de promoção
  4. Exclusivo, com requisição de atualização na escrita
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Dois contadores independentes de 8 bytes ocupam 0x3000 e 0x3038 com blocos de cache de 64 bytes. Cada um tem sua própria thread escritora. Que mudança os separa em blocos diferentes?
  1. Mover o segundo contador para 0x3020.
  2. Mover o segundo contador para 0x3040.
  3. Mover o primeiro contador para 0x3008.
  4. Mover o segundo contador para 0x3010.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Travou em uma questão sua? Ajuda com Tarefas

Termos-Chave

100 Termos-Chave, cada um com sua definição

A

Aceleração
Aceleração é o melhor tempo de execução sequencial dividido pelo tempo de execução paralela para a carga de trabalho comparada.
Um programa que termina em 12 s em vez de 60 s tem aceleração de cinco em relação à sua referência sequencial.
Aceleração superlinear
Aceleração superlinear é uma aceleração medida que supera o número de processadores, possível quando o particionamento paralelo também reduz o custo do trabalho.
Um melhor ajuste à cache pode produzir aceleração superlinear quando cada partição evita as faltas na DRAM da execução sequencial.
Acelerador de domínio específico
Um acelerador de domínio específico especializa o hardware para uma carga de trabalho restrita, trocando flexibilidade por alto desempenho por watt nesse domínio.
Um acelerador de domínio específico orientado a matrizes pode favorecer multiplicação de baixa precisão para trabalho com redes neurais.
Acesso com passo constante
Um acesso com passo constante visita elementos sucessivos com um espaçamento fixo entre endereços, como a distância entre entradas de uma coluna de matriz.
Um acesso com passo constante ao descer uma matriz de precisão dupla com 100 colunas avança 800 bytes entre entradas vizinhas da coluna.
Acesso indexado
Um acesso indexado obtém endereços de elementos a partir de índices, permitindo coletas e dispersões vetoriais irregulares além dos passos fixos.
Um acesso indexado pode buscar as entradas selecionadas de um vetor indicadas por uma lista irregular de posições.
Acesso não uniforme à memória (NUMA)
NUMA é uma organização de memória compartilhada em que o custo de acesso à memória depende da localização do processador em relação aos dados.
Uma carga de trabalho NUMA pode reduzir a latência média ao colocar páginas usadas com frequência perto das threads que as acessam.
Acesso uniforme à memória (UMA)
UMA é uma organização de memória compartilhada com tempo de acesso aproximadamente uniforme dos processadores às posições de memória.
Uma pequena máquina UMA apresenta caminhos de acesso à memória semelhantes, sem distinção entre soquete local e remoto.
Aglomerado de computadores
Um aglomerado de computadores é um conjunto de computadores completos conectados por rede, cada um com sua própria memória e seu próprio sistema operacional.
Um aglomerado distribui um grande vetor entre nós e combina seus resultados locais por mensagens de rede.

Á

Árvore de redução
Uma árvore de redução combina resultados parciais em estágios paralelos sucessivos, reduzindo muitos valores a um por um caminho dependente curto.
Uma árvore de redução combina 32 somas parciais em cinco estágios de formação de pares em vez de 31 adições consecutivas.

B

Barreira de potência
A barreira de potência é a restrição de potência e calor que limita os ganhos de desempenho obtidos ao continuar elevando as frequências de clock dos processadores.
A barreira de potência incentivou projetistas de chips a usar transistores adicionais para incluir mais núcleos de processamento.
Barreira de sincronização
Uma barreira de sincronização é um ponto ao qual todas as threads participantes devem chegar antes que qualquer uma continue para a próxima fase.
Uma barreira entre estágios de redução impede que uma unidade de trabalho leia uma soma parcial antes que ela seja escrita.
Bloco de threads
Um bloco de threads é um grupo de threads de GPU que podem cooperar pela memória compartilhada e se sincronizar com uma barreira que abrange o bloco.
Um bloco de threads pode combinar suas somas parciais, enquanto um kernel posterior combina resultados de blocos separados.
Busca e soma atômica
Busca e soma atômica é uma operação atômica que retorna o valor anterior de uma posição enquanto soma uma quantidade especificada de forma indivisível.
A busca e soma atômica pode preservar cada incremento quando várias threads atualizam um contador compartilhado concorrentemente.

C

Coalescência de acessos à memória
A coalescência de acessos à memória combina acessos próximos de threads vizinhas em um pequeno número de transações largas para usar a largura de banda com eficiência.
A coalescência funciona bem quando threads consecutivas de um warp leem elementos consecutivos de 4 bytes de um vetor.
Coerência de cache
A coerência de cache coordena cópias de uma posição para que os processadores observem um histórico compatível de suas escritas e valores de leitura.
A coerência de cache impede que um leitor use indefinidamente uma cópia privada desatualizada depois que outro núcleo a atualiza.
Compartilhamento verdadeiro
Compartilhamento verdadeiro ocorre quando processadores se comunicam pela mesma palavra de memória, de modo que sua interação de coerência diz respeito aos mesmos dados.
Um produtor escreve um valor que um consumidor lê, criando compartilhamento verdadeiro dessa variável de comunicação.
Comprimento do vetor
O comprimento do vetor é o número de elementos ativos processados por instruções vetoriais sob a configuração vetorial atual.
Um comprimento de vetor curto permite que a última passagem de um laço atualize seus oito elementos restantes sem executar um trecho escalar final separado.
Computador em escala de centro de dados
Um computador em escala de centro de dados opera um grande edifício com servidores em rede, alimentação elétrica e refrigeração como uma plataforma única para serviços e trabalho em lote.
Um computador em escala de centro de dados deve considerar energia e falhas rotineiras, além da vazão de requisições.
Concorrência
Concorrência é o progresso de várias tarefas durante períodos sobrepostos, incluindo a alternância em um recurso de execução.
Um sistema operacional de núcleo único permite concorrência ao alternar entre um download e um editor.
Consistência sequencial
A consistência sequencial exige resultados correspondentes a um entrelaçamento de todas as operações dos processadores que preserve a ordem do programa de cada processador.
A consistência sequencial restringe o histórico combinado sem exigir que os processadores sejam executados na mesma velocidade.

D

Dependência entre iterações do laço
Uma dependência entre iterações do laço ocorre quando uma iteração exige um valor produzido por outra, restringindo sua ordem de execução.
Uma recorrência acumulativa tem uma dependência entre iterações do laço porque cada novo valor usa o resultado anterior.
Diretório de coerência
Um diretório de coerência registra o estado de coerência e as caches que possuem blocos de memória para que requisições possam ser enviadas às caches pertinentes.
Um diretório encaminha uma requisição de leitura à cache que possui a cópia modificada mais recente em vez de difundi-la.
Disponibilidade
Disponibilidade é a capacidade de um serviço permanecer utilizável apesar de falhas, apoiada em grande escala por redundância, novas tentativas e redirecionamento.
Um serviço em escala de centro de dados protege a disponibilidade ao direcionar novas requisições para longe de um servidor com falha.
Distribuição de uma requisição entre servidores
A distribuição de uma requisição entre servidores consiste em enviar o trabalho de uma requisição a vários servidores cujas respostas necessárias contribuem para sua conclusão.
Uma distribuição maior da requisição dá a uma lentidão rara em qualquer servidor mais chances de atrasar a requisição completa.
Divergência de desvios
Divergência de desvios ocorre quando threads de um warp seguem caminhos diferentes, exigindo que esses caminhos sejam executados com máscaras ativas diferentes.
A divergência de desvios pode deixar metade de um warp inativa enquanto as threads atribuídas ao outro caminho são executadas.

E

Efetividade do uso de energia (PUE)
PUE é a razão entre a energia total da instalação e a energia dos equipamentos de TI no mesmo período, medindo a sobrecarga energética fora da carga de TI.
Uma PUE de 1,2 significa que a energia total da instalação é 20% superior à energia de TI, sem medir o trabalho útil dentro dos servidores.
Eficiência energética
Eficiência energética compara o trabalho útil concluído com a energia consumida, incluindo se os recursos dos servidores são usados de forma eficaz.
Uma instalação pode melhorar a PUE enquanto mantém baixa a eficiência energética dos servidores se grande parte de sua carga de TI não realiza trabalho útil.
Eficiência paralela
Eficiência paralela é a aceleração dividida pelo número de processadores, expressando o ganho útil em relação aos processadores alocados.
Uma aceleração de seis em oito processadores dá eficiência paralela de 75%, embora a redução de tempo seja maior.
Encadeamento
O encadeamento sobrepõe operações vetoriais dependentes ao permitir que uma instrução consumidora comece nos primeiros elementos antes que a produtora termine todos eles.
O encadeamento permite que uma adição use os primeiros produtos enquanto o pipeline de multiplicação continua gerando os produtos posteriores.
Equilíbrio de carga
Equilíbrio de carga é a distribuição do trabalho útil entre processadores de modo que o excesso de carga de uma unidade de trabalho não atrase desnecessariamente a fase.
Um mau equilíbrio de carga deixa sete unidades de trabalho esperando enquanto uma termina uma partição desproporcionalmente grande.
Escalabilidade forte
A escalabilidade forte mede como o tempo decorrido muda à medida que mais processadores executam o mesmo problema computacional de tamanho fixo.
Um experimento de escalabilidade forte mantém fixa a quantidade de células de uma simulação enquanto aumenta o número de processadores alocados.
Escalabilidade fraca
A escalabilidade fraca aumenta o trabalho total proporcionalmente ao número de processadores, mantendo constante o trabalho por processador durante o experimento.
Um experimento de escalabilidade fraca dobra os dados quando dobra os processadores e depois compara os tempos decorridos.
Estado compartilhado (S)
O estado compartilhado identifica uma cópia limpa, somente de leitura, de um bloco em cache que também pode estar presente em outras caches.
Quem escreve deve solicitar a posse antes de alterar um bloco no estado compartilhado porque outros leitores podem possuí-lo.
Estado exclusivo (E)
O estado exclusivo em MESI identifica um bloco limpo mantido por apenas uma cache, permitindo uma transição silenciosa para modificado em uma escrita.
Uma leitura seguida de uma escrita privada se beneficia do estado exclusivo porque a escrita não precisa de uma requisição de promoção.
Estado inválido (I)
O estado inválido identifica um bloco de cache cujo conteúdo não pode ser usado para atender a um acesso de leitura ou escrita do processador.
Uma leitura posterior de um bloco no estado inválido deve obter uma cópia válida pela hierarquia de memória.
Estado modificado (M)
O estado modificado identifica a única cópia válida em cache de um bloco, com dados que foram escritos e são mais recentes que a memória.
Um núcleo pode atualizar um bloco no estado modificado repetidamente sem obter permissão de escrita novamente.
Estrutura de vetores
Uma estrutura de vetores armazena os valores de cada campo em um vetor separado, tornando contíguos os valores de um campo para acesso vetorial.
Uma estrutura de vetores mantém todas as coordenadas x juntas quando um laço de geometria processa apenas esse campo.

F

Falso compartilhamento
Falso compartilhamento é a interferência de coerência entre núcleos que acessam variáveis diferentes em um bloco de cache quando pelo menos um núcleo escreve.
O falso compartilhamento pode tornar lentos contadores separados quando suas threads escritoras trocam repetidamente a posse de um bloco.
Falta de coerência
Uma falta de coerência ocorre quando um acesso deve buscar novamente um bloco que uma ação de coerência de outro processador invalidou.
Quem escreve em uma variável vizinha pode causar uma falta de coerência mesmo quando a própria variável do leitor nunca muda.
Fração sequencial
A fração sequencial é a parcela do tempo de execução de referência que não pode ser dividida entre processadores no modelo paralelo.
Uma fração sequencial de 0,1 deixa um décimo do tempo original mesmo que todo o trabalho paralelo deixe de ter custo.

G

Grade de blocos
Uma grade de blocos é o conjunto de blocos de threads criado pelo lançamento de um kernel de GPU, cujos blocos comuns podem ser executados em qualquer ordem.
Uma grade deve conter blocos suficientes para cobrir todos os dados quando o kernel trata apenas um elemento por thread.
Granularidade
Granularidade é a quantidade de cálculo realizada entre eventos de comunicação ou sincronização em um cálculo paralelo.
Uma granularidade maior pode reduzir o custo de mensagens por operação, mas deixar poucas partes para um bom equilíbrio de carga.

H

Hospedeiro
O hospedeiro é o lado da CPU de um programa heterogêneo, responsável por organizar armazenamento no dispositivo, transferências, lançamentos e uso dos resultados.
O hospedeiro pode continuar após um lançamento, mas deve esperar pelos resultados concluídos do dispositivo antes de consumi-los.

I

Identificador do processo no comunicador
Um identificador do processo no comunicador é o identificador de um processo MPI dentro de um comunicador, usado para selecionar participantes e atribuir dados ou funções de comunicação.
Um processo usa seu identificador para determinar qual partição do vetor somar e para onde enviar seu resultado parcial.
Instrução única e múltiplas threads (SIMT)
SIMT é um estilo de execução de GPU que apresenta threads independentes enquanto emite uma instrução para as threads ativas de um grupo.
Código SIMT calcula um índice por thread, embora a emissão de instruções seja compartilhada dentro de cada warp.
Intensidade aritmética
Intensidade aritmética é o número de operações de ponto flutuante por byte transferido; em um modelo Roofline da DRAM, ela conta os bytes na fronteira da DRAM.
A reutilização na cache aumenta a intensidade aritmética quando a contagem de operações úteis permanece fixa, mas o tráfego da DRAM diminui.
Interface de passagem de mensagens (MPI)
MPI é uma interface padronizada de passagem de mensagens para que processos troquem dados e realizem operações coletivas em um programa paralelo.
Uma redução MPI combina somas parciais distribuídas sem tratar dados de nós remotos como ponteiros locais comuns.

K

Kernel
Um kernel é uma função de dispositivo lançada sobre muitas threads de GPU, cada uma executando a função com seus próprios índices e dados.
Um kernel SAXPY atribui um elemento do vetor a cada thread válida e verifica o limite superior do índice.
Kernel limitado pela capacidade de cálculo
Um kernel limitado pela capacidade de cálculo tem intensidade suficiente para que a capacidade aritmética de pico seja o menor limite no modelo Roofline.
A blocagem pode aproximar um cálculo da condição de kernel limitado pela capacidade de cálculo ao reutilizar dados em muitas operações aritméticas.
Kernel limitado pela largura de banda da memória
Um kernel limitado pela largura de banda da memória tem um teto de largura de banda da memória menor que o teto de cálculo, portanto sua taxa máxima depende do fornecimento de dados.
Quando um kernel limitado pela largura de banda da memória satura a largura de banda da DRAM, unidades aritméticas mais largas, por si só, não podem elevar seu limite no modelo Roofline.

L

Lançamento assíncrono
Um lançamento assíncrono inicia trabalho no dispositivo sem fazer o hospedeiro esperar que esse trabalho termine antes de continuar a execução.
Um lançamento assíncrono precisa de uma verificação posterior de conclusão ou de uma cópia bloqueante dos resultados antes de seu uso pelo hospedeiro.
Largura de banda de bisseção
Largura de banda de bisseção é a menor capacidade total de enlaces através de um corte que divide os nós de uma rede em dois grupos de mesmo tamanho.
Um anel tem apenas dois enlaces através de um corte mínimo, portanto sua largura de banda de bisseção pode limitar o tráfego entre as metades.
Largura de banda do enlace
Largura de banda do enlace é a taxa de dados disponível em um enlace de rede, medida segundo uma convenção consistente de capacidade direcional.
Uma topologia com mais enlaces pode ter maior capacidade total mesmo quando a largura de banda de cada enlace permanece inalterada.
Largura do registrador vetorial em bits (VLEN)
VLEN é a largura em bits do registrador vetorial de uma implementação RVV, distinta da contagem de elementos ativos e da contagem de vias de execução paralelas.
Uma VLEN maior pode comportar mais elementos, enquanto o programa ainda avança pelo comprimento ativo que recebe.
Latência de cauda
Latência de cauda é a extremidade de maior atraso dos tempos de resposta, que pode dominar uma requisição que precisa de respostas de muitos servidores.
Uma requisição distribuída entre servidores espera pela resposta necessária mais lenta, tornando a latência de cauda de um servidor uma preocupação para todo o serviço.
Lei de Amdahl
A lei de Amdahl determina a aceleração global de uma melhoria usando a fração do tempo original que ela afeta e a aceleração dessa fração.
A lei de Amdahl explica por que tornar uma pequena parte de um programa muito mais rápida pode alterar pouco seu tempo total.
Lei de Gustafson
A lei de Gustafson estima a aceleração com tamanho escalonado a partir do número de processadores e da fração de tempo sequencial medida na execução paralela.
A lei de Gustafson descreve como um problema paralelo maior pode usar uma máquina maior dentro de um tempo disponível semelhante.
Leitura-modificação-escrita atômica
Uma leitura-modificação-escrita atômica atualiza uma posição de memória de forma indivisível para os outros processadores, combinando a leitura e a escrita.
A leitura-modificação-escrita atômica impede que dois incrementos de contador sobrescrevam o mesmo valor antigo.

M

Máscara
Uma máscara seleciona elementos ativos de uma operação SIMD ou vetorial, permitindo trabalho condicional sem um fluxo de instruções separado por via.
Uma máscara pode impedir atualizações de elementos do vetor que não passam em uma comparação ou estão além do trecho final válido.
Memória compartilhada
Memória compartilhada é o armazenamento de GPU no chip, gerenciado pelo programa e disponível às threads de um bloco para cooperação e reutilização de dados.
Um bloco carrega uma parte dos dados na memória compartilhada antes de reutilizá-la em várias operações aritméticas.
Memória global
Memória global é a DRAM do dispositivo GPU acessível em toda a grade, com acessos atendidos pela hierarquia de caches do dispositivo.
Um kernel pode reutilizar blocos na memória compartilhada para reduzir o número de vezes que relê dados da memória global.
MIMD
MIMD é uma classe de hardware com múltiplos fluxos de instruções controlados independentemente que operam em múltiplos fluxos de dados.
Um aglomerado de computadores é MIMD quando seus nós avançam independentemente em seus cálculos e trocam mensagens.
MISD
MISD é a classe de hardware com múltiplos fluxos de instruções atuando sobre um fluxo de dados; poucas máquinas práticas se enquadram nela de forma clara.
A designação MISD completa as quatro combinações de fluxo único e múltiplo, enquanto os exemplos reais propostos frequentemente dependem de interpretação.
Modelo de consistência de memória
Um modelo de consistência de memória define as ordenações observáveis e os resultados permitidos de leituras e escritas, incluindo em posições diferentes.
Um modelo de consistência de memória determina como outro processador pode observar acessos a um indicador e a seus dados.
Modelo Roofline
O modelo Roofline limita o desempenho aritmético alcançável ao menor valor entre a capacidade de cálculo de pico e a largura de banda multiplicada pela intensidade.
O modelo Roofline ajuda a decidir se operações aritméticas mais rápidas ou menos movimentação de dados podem elevar o limite de um kernel.
Monitoração de requisições de coerência
A monitoração de requisições de coerência é um método em que controladores de cache observam requisições difundidas e atualizam as permissões ou os dados de seus blocos.
A monitoração de requisições de coerência permite que um detentor no estado modificado detecte a requisição de leitura de outro núcleo e forneça o conteúdo atual do bloco.
Multiprocessador de memória compartilhada
Um multiprocessador de memória compartilhada permite que processadores se comuniquem por cargas e armazenamentos em um espaço de endereçamento físico.
Um multiprocessador de memória compartilhada ainda pode ter caches privadas separadas e memória distribuída entre soquetes.
Multiprocessador de streaming
Um multiprocessador de streaming é uma unidade de processamento em GPUs NVIDIA que escalona warps residentes entre vias aritméticas e armazenamento no chip.
Um multiprocessador de streaming pode emitir instruções de outro warp pronto quando um warp residente espera pela memória global.
Multithreading de granularidade fina
O multithreading de granularidade fina seleciona uma thread a cada ciclo de clock, normalmente alternando entre contextos prontos e pulando os que estão parados.
O multithreading de granularidade fina pode alternar períodos curtos de várias threads para cobrir paradas do pipeline.
Multithreading de granularidade grossa
O multithreading de granularidade grossa troca de thread em paradas longas, permitindo execução prolongada de uma única thread entre trocas custosas.
O multithreading de granularidade grossa pode trocar de thread após uma falta na cache de último nível que exige um acesso longo à memória.
Multithreading em hardware
O multithreading em hardware mantém vários contextos de thread em um núcleo para que ele possa executar trabalho pronto enquanto outra thread está parada.
O multithreading em hardware pode preencher ciclos de espera pela memória sem duplicar um núcleo físico completo.
Multithreading simultâneo
O multithreading simultâneo permite que um núcleo de emissão múltipla emita instruções de threads de hardware diferentes no mesmo ciclo.
O multithreading simultâneo preenche posições livres de emissão quando uma thread não consegue fornecer instruções prontas suficientes.

N

Nó de origem
Um nó de origem gerencia a entrada de diretório de um determinado bloco de memória e coordena requisições envolvendo as cópias desse bloco em cache.
Blocos diferentes podem ter nós de origem diferentes, distribuindo o armazenamento do diretório e o tratamento de requisições.

O

Ocultação de latência
A ocultação de latência executa outro trabalho pronto durante uma espera, melhorando o uso dos recursos sem reduzir a duração da própria operação pendente.
Uma GPU usa ocultação de latência quando seu escalonador seleciona outro warp durante um acesso pendente à memória.

P

Paralelismo
Paralelismo é a execução simultânea de operações em recursos de hardware distintos para reduzir a latência ou aumentar a vazão.
Uma simulação usa paralelismo quando vários núcleos atualizam regiões independentes no mesmo instante.
Paralelismo em nível de dados
O paralelismo em nível de dados aplica a mesma operação a vários elementos de dados independentes, frequentemente usando vias SIMD ou threads de GPU.
Somar elementos correspondentes de vetores oferece paralelismo em nível de dados porque cada par pode ser processado independentemente.
Paralelismo em nível de instrução
O paralelismo em nível de instrução sobrepõe instruções de um fluxo de instruções por técnicas como segmentação em pipeline e emissão múltipla.
Um núcleo explora o paralelismo em nível de instrução ao emitir duas adições escalares independentes em conjunto.
Paralelismo em nível de requisição
O paralelismo em nível de requisição executa tarefas ou requisições de serviço independentes ao mesmo tempo, com pouca coordenação entre seus cálculos.
Um serviço de busca obtém paralelismo em nível de requisição de milhares de usuários que fazem perguntas independentes.
Paralelismo em nível de thread
O paralelismo em nível de thread executa várias threads ao mesmo tempo, cada uma com seu próprio contador de programa e estado de registradores.
Um renderizador de imagens usa paralelismo em nível de thread ao atribuir regiões diferentes da imagem a diferentes unidades de trabalho.
Particionamento do laço em blocos
O particionamento do laço em blocos divide um laço longo em partes que cabem na configuração vetorial, atualizando o progresso após cada parte processada.
O particionamento do laço em blocos pode processar 100 elementos com comprimentos ativos sucessivos de 32, 32, 32 e quatro.
Ponto de transição do modelo Roofline
O ponto de transição do modelo Roofline é a intensidade em que o teto de largura de banda encontra o teto de cálculo, igual à capacidade de cálculo de pico dividida pela largura de banda.
Um ponto de transição de dez FLOPs por byte coloca um kernel de dois FLOPs por byte abaixo da região limitada pela capacidade de cálculo.
Processador lógico
Um processador lógico é um contexto de thread de hardware visível ao sistema operacional como um local onde uma thread de software pode ser executada.
Um chip de seis núcleos com dois contextos por núcleo apresenta doze processadores lógicos que compartilham seis núcleos.
Propagação de escritas
Propagação de escritas é o requisito de coerência segundo o qual uma escrita de um processador acaba se tornando visível às leituras dos outros processadores.
A propagação de escritas garante que um novo valor não permaneça permanentemente oculto na cache privada de quem o escreveu.
Proporcionalidade energética
Proporcionalidade energética é o objetivo de projeto segundo o qual o consumo de potência deve aumentar proporcionalmente à carga útil tratada por um sistema.
Uma potência ociosa alta enfraquece a proporcionalidade energética porque um servidor com pouca carga ainda consome energia significativa.
Protocolo de invalidação na escrita
Um protocolo de invalidação na escrita concede permissão exclusiva de escrita a quem escreve ao tornar inutilizáveis outras cópias em cache de seu bloco.
Um protocolo de invalidação na escrita permite que um detentor realize escritas repetidas no estado modificado sem difundir cada novo valor.

S

Serialização de escritas
A serialização de escritas exige que cada processador concorde com a ordem das escritas na mesma posição em um sistema de memória coerente.
A serialização de escritas impede que processadores observem ordens opostas para duas escritas na mesma posição X.
SIMD
SIMD é uma classe de hardware em que uma instrução controla a mesma operação em vários elementos de dados ou vias aritméticas.
Uma adição de vetores com oito vias é SIMD mesmo realizando oito adições de elementos com uma instrução emitida.
SISD
SISD é uma classe de hardware com um fluxo de instruções e um fluxo de dados, incluindo núcleos escalares convencionais segmentados em pipeline.
Um núcleo escalar em pipeline continua sendo SISD porque as instruções sobrepostas ainda seguem um fluxo de instruções.
Sobrecarga do paralelismo
Sobrecarga do paralelismo é o custo de execução acrescentado pela organização paralela, como escalonamento, comunicação, sincronização ou trabalho extra.
A sobrecarga do paralelismo pode crescer tanto que uma tarefa leva mais tempo depois que seu número de processadores aumenta.
Sobreposição de referências (aliasing)
A sobreposição de referências ocorre quando referências diferentes podem acessar áreas de armazenamento sobrepostas, o que pode tornar inseguras operações simultâneas de um laço.
Um compilador verifica a sobreposição de referências antes de reordenar cargas e armazenamentos por ponteiros que podem se sobrepor.
Sobressubscrição da rede
A sobressubscrição da rede ocorre quando enlaces superiores oferecem menos capacidade que a capacidade agregada dos enlaces inferiores que os alimentam.
Um rack com 400 Gbit/s de enlaces de servidores e 100 Gbit/s de enlaces de subida tem sobressubscrição de 4:1.
SPMD
SPMD é um estilo de programação em que unidades de trabalho executam cópias do mesmo programa e usam seus identificadores para selecionar dados diferentes.
Uma soma de vetor em SPMD usa o identificador de cada unidade de trabalho para escolher uma região antes de combinar os resultados parciais.

T

Taxonomia de Flynn
A taxonomia de Flynn classifica o hardware conforme os fluxos de instruções e de dados sejam únicos ou múltiplos em um nível escolhido da máquina.
A taxonomia de Flynn pode descrever núcleos independentes de CPU de forma diferente das unidades SIMD dentro desses núcleos.
Teto de desempenho
Um teto de desempenho é um limite mais baixo em uma análise Roofline que representa uma restrição, como a falta de SIMD ou padrões de acesso inadequados.
Um teto de largura de banda abaixo do teto principal pode mostrar o desempenho perdido devido a acessos ineficientes à memória.
Topologia em toro
Uma topologia em toro é uma rede em malha com enlaces que conectam extremidades opostas, acrescentando caminhos e aumentando a capacidade de seção transversal.
Um toro de 8 por 8 tem 128 enlaces, incluindo as conexões entre extremidades que uma malha comum não possui.

V

Verificação de limites
Uma verificação de limites testa se um índice calculado está dentro do intervalo válido de dados antes que uma thread faça o acesso à memória associado.
Quando uma grade é arredondada para cima até blocos inteiros, uma verificação de limites desativa as threads extras no último bloco sem ignorar elementos válidos.
Vetor de presença
Um vetor de presença usa um bit por núcleo para registrar quais caches possuem determinado bloco em um diretório com vetor completo.
Um vetor de presença para 64 núcleos exige oito bytes por bloco rastreado antes dos bits de estado de coerência.
Vetorização automática
Vetorização automática é uma transformação do compilador que converte trabalho adequado de laços escalares em operações SIMD, preservando os resultados exigidos.
Uma possível sobreposição de ponteiros pode impedir a vetorização automática, a menos que uma verificação estabeleça que os vetores não se sobrepõem.
Via SIMD
Uma via SIMD é uma posição de elemento e seu trabalho aritmético associado dentro de uma operação larga controlada por uma instrução compartilhada.
Uma adição de 256 bits tem oito vias SIMD para números de ponto flutuante de 32 bits, mas quatro vias para números de precisão dupla de 64 bits.

W

Warp
Um warp é um grupo de 32 threads no modelo de execução da NVIDIA; as threads ativas compartilham a emissão de instruções e mantêm dados separados.
Threads de um warp podem usar índices consecutivos para que suas cargas sejam combinadas em transações de memória eficientes.

Sobre esta aula

Por StudeliRelatar um erro

Crie seus próprios Materiais de Estudo

Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.

Começar