Voltar aos Cursos
AI032 Professional

Programação de Processadores Massivamente Paralelos: Uma Abordagem Prática

Este curso oferece uma introdução abrangente ao computação em GPU e programação paralela usando o ambiente CUDA C. Aborda arquiteturas de GPU, paralelismo de dados, gerenciamento de threads, otimização de memória e considerações avançadas de desempenho, ilustradas por estudos de caso do mundo real como reconstrução de ressonância magnética e visualização molecular.

4.9
36.0h
569 estudantes
0 curtidas
Inteligência Artificial
Começar a Aprender

Visão Geral do Curso

📚 Resumo do Conteúdo

Este curso oferece uma introdução abrangente ao computação em GPU e programação paralela usando o ambiente CUDA C. Ele aborda arquiteturas de GPU, paralelismo de dados, gerenciamento de threads, otimização de memória e considerações avançadas de desempenho, ilustrados por estudos de caso do mundo real, como reconstrução de ressonância magnética e visualização molecular.

Domine a arte da computação paralela de alto desempenho com um guia prático e baseado em exercícios sobre CUDA e arquiteturas de GPU.

Autor: David B. Kirk, Wen-mei W. Hwu

Agradecimentos: Ian Buck, John Nickolls, equipe NVIDIA DevTech, Jensen Huang, David Luebke, Bill Bean, Simon Green, Mark Harris, Manju Hedge, Nadeem Mohammad, Brent Oster, Peter Shirley, Eric Young e Cyril Zeller.

🎯 Objetivos de Aprendizagem

  1. Distinguir entre os filosofias de design e trajetórias de desempenho de CPUs multicore e GPUs many-core.
  2. Identificar os componentes principais de uma arquitetura de GPU moderna, incluindo Multiprocessadores de Fluxo (SMs) e estruturas de memória.
  3. Aplicar a Lei de Amdahl para calcular o ganho teórico de velocidade e identificar o impacto de gargalos sequenciais.
  4. Contrastar as diferenças arquitetônicas entre pipelines fixos e matrizes de processadores unificadas programáveis.
  5. Explicar o papel do "GPGPU" como um passo intermediário e as restrições dos modelos iniciais de programação de shaders.
  6. Analisar como recursos de hardware como operações atômicas, sincronização de barreira e suporte a precisão dupla permitiram a transição para computação geral escalável.
  7. Identificar e explorar o paralelismo de dados em algoritmos de multiplicação de matrizes.
  8. Implementar o gerenciamento de memória do dispositivo, incluindo alocação, transferência de dados entre host e dispositivo e desalocação.
  9. Criar e lançar kernels CUDA usando indexação de thread e configurações apropriadas de grade/bloco.
  10. Projetar hierarquias multidimensionais de threads (grades e blocos) para mapear estruturas de dados complexas no hardware da GPU.

🔹 Lição 1: Introdução à Computação Paralela e Arquiteturas de GPU

Visão Geral: Esta lição explora a mudança fundamental da computação sequencial para a computação paralela, impulsionada pelas filosofias de design divergentes de CPUs e GPUs. Os alunos examinarão as trajetórias "Multicore" versus "Many-core", compreenderão a arquitetura de hardware que permite às GPUs alcançar grande throughput e aprenderão as restrições matemáticas do ganho de velocidade via Lei de Amdahl.

Resultados de Aprendizagem:

  • Distinguir entre as filosofias de design e trajetórias de desempenho de CPUs multicore e GPUs many-core.
  • Identificar os componentes principais de uma arquitetura de GPU moderna, incluindo Multiprocessadores de Fluxo (SMs) e estruturas de memória.
  • Aplicar a Lei de Amdahl para calcular o ganho teórico de velocidade e identificar o impacto de gargalos sequenciais.

🔹 Lição 2: A Evolução e o Futuro da Computação em GPU

Visão Geral: Esta lição traça a jornada arquitetônica da Unidade de Processamento Gráfico (GPU) desde seu surgimento como hardware especializado de função fixa para renderizar triângulos até sua atual condição como poderoso processador paralelo unificado e de propósito geral. Os alunos explorarão a transição de pipelines rígidos para shaders programáveis, o surgimento do movimento GPGPU e as arquiteturas escaláveis modernas que impulsionam simulações científicas e de engenharia atuais.

Resultados de Aprendizagem:

  • Contrastar as diferenças arquitetônicas entre pipelines fixos e matrizes de processadores unificadas programáveis.
  • Explicar o papel do "GPGPU" como um passo intermediário e as limitações dos modelos iniciais de programação de shaders.
  • Analisar como recursos de hardware como operações atômicas, sincronização de barreira e suporte a precisão dupla permitiram a transição para computação geral escalável.

🔹 Lição 3: Estrutura de Programas CUDA e Gerenciamento de Memória

Visão Geral: Esta lição cobre a arquitetura fundamental de um programa CUDA, enfatizando a distinção entre execução Host (CPU) e Device (GPU). Os alunos aprenderão a identificar paralelismo de dados em operações de matriz, gerenciar espaços de memória separados usando a API CUDA e organizar a execução paralela por meio de uma hierarquia de grades, blocos e threads usando o estilo Single-Program, Multiple-Data (SPMD).

Resultados de Aprendizagem:

  • Identificar e explorar o paralelismo de dados em algoritmos de multiplicação de matrizes.
  • Implementar o gerenciamento de memória do dispositivo, incluindo alocação, transferência de dados entre host e dispositivo e desalocação.
  • Criar e lançar kernels CUDA usando indexação de thread e configurações apropriadas de grade/bloco.

🔹 Lição 4: Threads e Escalonamento Avançados em CUDA

Visão Geral: Esta lição explora a organização hierárquica de threads em CUDA, focando na forma como o indexamento multidimensional se mapeia para dados físicos e recursos de hardware. Detalha os mecanismos de sincronização de barreira e escalabilidade transparente, concluindo com os princípios arquitetônicos de atribuição de threads e escalonamento baseado em warp usados para alcançar tolerância a latência em computação de alto desempenho.

Resultados de Aprendizagem:

  • Projetar hierarquias multidimensionais de threads (grades e blocos) para mapear estruturas de dados complexas no hardware da GPU.
  • Implementar indexação precisa de dados usando variáveis embutidas do CUDA (blockIdx, threadIdx, blockDim).
  • Aplicar sincronização de barreira para garantir integridade de dados enquanto mantém escalabilidade transparente em diferentes arquiteturas de GPU.

🔹 Lição 5: Otimização de Memória e Tileamento de Memória Compartilhada

Visão Geral: Esta lição explora como a largura de banda de memória e as restrições de recursos atuam como gargalos primários na computação paralela. Detalha o uso do "tileamento" para reduzir o tráfego de memória global e explica o papel crítico das barras de sincronização (__syncthreads()) e da escolha estratégica entre registradores e memória compartilhada para otimizar o desempenho.

Resultados de Aprendizagem:

  • Analisar como os limites de registradores e memória compartilhada determinam o nível de paralelismo (ocupação) em um kernel.
  • Quantificar a redução no consumo de largura de banda de memória global alcançada por técnicas de tileamento.
  • Identificar a necessidade de funções de sincronização para manter a integridade dos dados durante o acesso à memória compartilhada.

🔹 Lição 6: Análise de Desempenho e Execução SIMT

Visão Geral: Esta lição explora as considerações arquitetônicas e algóricas essenciais para otimizar kernels CUDA. Transita dos modelos de execução básicos — especificamente a unidade Single-Instruction, Multiple-Thread (SIMT) e particionamento de warp — para técnicas avançadas de ajuste de desempenho, incluindo coalescimento de memória, multiplicação de matrizes com tileamento e particionamento dinâmico dos recursos do Streaming Multiprocessor (SM).

Resultados de Aprendizagem:

  • Analisar o mapeamento de blocos de threads multidimensionais para a ordem linear de execução de warp do hardware.
  • Avaliar e minimizar a divergência de fluxo de controle em algoritmos de redução paralela.
  • Otimizar a largura de banda de memória global implementando padrões de acesso coalescido e com tileamento.

🔹 Lição 7: Aritmética de Ponto Flutuante e Precisão Numérica

Visão Geral: Esta lição aborda a arquitetura fundamental dos números de ponto flutuante, focando nos componentes do padrão IEEE 754: sinal, expoente codificado com excesso e mantissa normalizada. Os alunos explorarão como esses padrões de bits se mapeiam para uma reta numérica discreta e como as limitações dessa representação afetam a precisão de algoritmos complexos como somas em larga escala.

Resultados de Aprendizagem:

  • Desmontar o formato de ponto flutuante para calcular valores numéricos a partir de padrões de bits usando representação normalizada e codificação com excesso.
  • Visualizar a distribuição de números representáveis em uma reta numérica e explicar o impacto da alocação de bits entre expoente e mantissa.
  • Quantificar a imprecisão numérica usando ULP e identificar como diferentes modos de arredondamento contribuem para erros.

🔹 Lição 8: Estudo de Caso: Paralelização da Reconstrução de Ressonância Magnética

Visão Geral: Esta lição explora a paralelização da reconstrução avançada de Ressonância Magnética (MRI) em GPUs. Foca no processo iterativo de reconstrução para trajetórias não-Cartesianas, especificamente otimizando o kernel computacionalmente intenso F^H d por meio de transformações de loop, gerenciamento de memória constante, reorganização de layout de dados e uso de funções trigonométricas aceleradas por hardware.

Resultados de Aprendizagem:

  • Compreender a transição da reconstrução baseada em FFT Cartesiana para algoritmos baseados em resolvedores lineares iterativos para dados de k-space não-Cartesianos.
  • Aplicar fission de loop e troca de loop para transformar código C sequencial em uma estrutura adequada para mapeamento massivo de threads CUDA.
  • Otimizar o throughput de memória usando chunking de memória constante e layouts de dados Array-of-Structs (AoS).

🔹 Lição 9: Estudo de Caso: Visualização Molecular e Execução Multi-GPU

Visão Geral: Esta lição explora a aplicação prática da computação em GPU à visualização molecular, especificamente usando o método de Soma Direta de Coulomb (DCS) para calcular mapas de potencial eletrostático. Os alunos evoluirão de uma implementação básica do kernel até versões altamente otimizadas que aproveitam o desenrolamento de instruções, coalescimento de memória e preenchimento.

Resultados de Aprendizagem:

  • Implementar um kernel de Soma Direta de Coulomb (DCS) usando memória constante CUDA e técnicas de ocultação de latência de memória global.
  • Otimizar o desempenho do kernel por meio do desenrolamento de instruções e reaproveitamento de cálculos comuns de coordenadas.
  • Aplicar estratégias de coalescimento de memória e preenchimento para alinhar acessos à memória global da GPU com a largura de banda máxima.

🔹 Lição 10: Pensamento Computacional e Seleção de Algoritmos Paralelos

Visão Geral: Esta lição explora a transição do pensamento sequencial para a resolução de problemas paralelos, focando nos objetivos da programação paralela e na seleção estratégica de algoritmos. Os alunos aprenderão a decompor problemas em unidades paralelizáveis, aplicar o pensamento computacional para pontuar entre ciência do domínio e arquitetura de hardware, e avaliar o desempenho de algoritmos.

Resultados de Aprendizagem:

  • Identificar os objetivos principais da programação paralela e calcular o ganho teórico de velocidade usando a Lei de Amdahl.
  • Diferenciar entre decomposição por tarefa e por dados e aplicar estratégias centradas no átomo (scatter) versus centradas na grade (gather).
  • Avaliar e selecionar algoritmos paralelos com base em critérios como largura de banda de memória, complexidade computacional e restrições arquitetônicas.

🔹 Lição 11: Introdução ao Modelo de Programação OpenCL

Visão Geral: Esta lição apresenta o OpenCL como um framework para computação paralela heterogênea, focando em seu modelo de paralelismo de dados e abstração hierárquica de hardware. Os alunos aprenderão a mapear as estruturas NDRange e de memória do OpenCL para equivalentes CUDA e dominar a gestão do lado host de dispositivos por meio de um modelo de compilação dinâmica.

Resultados de Aprendizagem:

  • Mapear o paralelismo e as hierarquias de memória do OpenCL para arquiteturas específicas do CUDA (por exemplo, mapear Work-groups para Blocos e Memória Local para Memória Compartilhada).
  • Implementar funções de kernel OpenCL e gerenciar o ambiente de execução do lado host usando Contextos e Filas de Comandos.
  • Executar o fluxo de trabalho de compilação dinâmica para construir kernels a partir de código-fonte em tempo de execução.

🔹 Lição 12: Recursos Modernos de GPU e Perspectiva Futura

Visão Geral: Esta lição explora a evolução arquitetônica e funcional das GPUs, focando na transição rumo a uma gestão de memória sofisticada, capacidades aprimoradas de execução de kernels e aumento do desempenho dos núcleos. Os alunos examinarão como recursos como Espaço de Memória Unificada do Dispositivo e chamadas de função de nível de kernel transpõem a GPU para um processador de propósito geral.

Resultados de Aprendizagem:

  • Explicar a importância da Evolução da Arquitetura de Memória e a transição rumo a um Espaço de Memória Unificada de 64 bits.
  • Analisar como Operações Atômicas Aprimoradas e Chamadas de Função de Nível de Kernel permitem a implementação de estruturas e algoritmos complexos.
  • Avaliar os impactos de desempenho da Execução Simultânea de Kernels, melhorias no desempenho de precisão dupla e Eficiência de Fluxo de Controle em ambientes de GPU modernos.