16 pontos por GN⁺ 2025-08-08 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Com a Lei de Moore chegando aos seus limites, o hardware evolui do foco em acelerar um único núcleo para múltiplos núcleos e processamento paralelo
  • O processamento paralelo se divide em várias formas, como paralelismo de dados, paralelismo de modelo e paralelismo de pipeline, sendo usado de forma combinada em sistemas modernos de deep learning
  • A paralelização acontece em diversas camadas, como SIMD (paralelismo de dados no nível de instrução), paralelismo de threads/cores e paralelismo massivo em GPU
  • As linguagens, bibliotecas e ferramentas para processamento paralelo em sua maioria são extensões “acopladas” a linguagens sequenciais já existentes, por isso ganha atenção a tendência de integrar o paralelismo nativamente à linguagem (como no Mojo)
  • A otimização prática de desempenho, como redução de compartilhamento de linhas de cache (interações desnecessárias), particionamento eficiente de memória e vetorização automática, é um desafio importante

Motivação do paralelismo e evolução do hardware

  • No início, o desempenho melhorava naturalmente com a miniaturização dos transistores e o aumento do clock, mas chegou a limites físicos por causa de restrições térmicas e de processo de fabricação
  • Depois disso, a arquitetura multicore virou padrão, com dezenas a centenas de núcleos em uma única CPU

Formas gerais de paralelismo

  • Paralelismo de dados: aplicar a mesma operação simultaneamente a muitos dados (ex.: soma de vetores)
  • Paralelismo de modelo: distribuir um modelo entre vários dispositivos
  • Paralelismo de pipeline: dividir o cálculo em várias etapas, com cada etapa operando ao mesmo tempo

SIMD (single instruction, multiple data) e vetorização

  • SIMD é uma forma de processar vários dados (vetores) com uma única instrução, com suporte em vários ISAs como ARM NEON e x86 SSE/AVX
  • Por meio de intrinsics em C/C++, é possível controlar explicitamente operações vetoriais; compiladores também oferecem vetorização automática, embora com limitações
  • Na prática, processa-se primeiro o volume correspondente ao comprimento do vetor e, em seguida, os dados restantes são tratados com operações escalares

Paralelização em CPU

  • Usa-se threads para execução paralela em múltiplos núcleos, com APIs por linguagem e suporte do escalonador do sistema operacional
  • Como o custo de criação e destruição de threads é alto, é mais eficiente dividir o trabalho em uma quantidade adequada de threads (próxima ao número de núcleos) em relação ao tamanho dos dados
  • É importante otimizar o "false sharing" de linha de cache (queda de desempenho quando threads diferentes acessam variáveis independentes na mesma linha de cache), usando por exemplo std::hardware_destructive_interference_size do C++17
  • É necessário aplicar padding/alinhamento para que cada thread escreva em uma área de dados separada

Paralelização em GPU

  • A GPU é especializada em processamento paralelo massivo de dados por meio de milhares de pequenos núcleos
  • CUDA/OpenCL: executam funções kernel em unidades de dezenas a dezenas de milhares de threads/blocos; internamente usam o modelo SIMT (single instruction, multiple threads)
  • O funcionamento por work groups/warps e a minimização de divergência de ramificação (branch divergence) são extremamente importantes para o desempenho
  • Hierarquia de memória: é necessário otimizar de forma hierárquica registradores de thread, memória compartilhada por bloco e memória global

Triton: DSL de kernels GPU baseada em Python

  • Triton é uma DSL embutida em Python, com suporte a compilação JIT e múltiplos backends (MLIR/LLVM/PTX etc.)
  • Permite escrever código de kernel em Python de alto nível, com suporte a paralelização, particionamento e masking automáticos
  • Entrega de 75% a 90% do desempenho do NVIDIA cuDNN, reduzindo drasticamente a complexidade de desenvolvimento

Tornando o paralelismo nativo na linguagem: Mojo

  • Mojo é uma nova linguagem criada por Chris Lattner, desenvolvedor de LLVM/MLIR, com suporte em nível de linguagem para paralelismo e compilação especializada em hardware
  • Tipos vetoriais SIMD, funções vetorizadas e distinção entre memória de host/device mostram que o paralelismo está embutido no sistema de tipos e na estrutura da linguagem
  • Até loops em estilo Python podem ser vetorizados automaticamente, permitindo desempenho sem necessidade de controle explícito de baixo nível

Conclusão e perspectivas

  • A programação paralela moderna é composta pela combinação de vários hardwares e modelos de paralelismo, e o suporte da própria linguagem vem se tornando cada vez mais importante
  • Com a ascensão de linguagens e ferramentas de próxima geração para paralelismo, como Mojo, Triton e JAX, a paralelização está evoluindo para algo mais intuitivo e produtivo
  • Na programação paralela, o desempenho máximo só pode ser alcançado quando arquitetura de hardware, otimização de memória e suporte da linguagem se combinam de forma orgânica

Ainda não há comentários.

Ainda não há comentários.