2 pontos por GN⁺ 2024-04-27 | 1 comentários | Compartilhar no WhatsApp

Visão geral da arquitetura tiny-gpu

GPU

  • Construída para executar um kernel por vez
  • Para executar um kernel, é necessário fazer o seguinte:
    1. Carregar a memória global de programa com o código do kernel
    2. Carregar a memória de dados com os dados necessários
    3. Definir, nos registradores de controle do dispositivo, o número de threads a executar
    4. Definir o sinal de início como HIGH para executar o kernel
  • A GPU é composta pelas seguintes unidades:
    1. Registradores de controle do dispositivo
    2. Dispatcher
    3. Um número variável de núcleos de computação
    4. Controlador de memória para memória de dados e memória de programa
    5. Cache

Memória

  • A GPU foi construída para fazer interface com memória global externa
  • A memória de dados e a memória de programa são separadas para simplificação
  • A memória global tem largura de banda fixa de leitura/escrita
  • O controlador de memória rastreia todas as requisições de saída dos núcleos de computação para a memória, ajusta as requisições de acordo com a largura de banda real da memória externa e retransmite as respostas da memória externa para o recurso apropriado
  • O cache armazena dados requisitados repetidamente para reduzir o uso da largura de banda da memória

Núcleos

  • Cada núcleo possui recursos de computação
  • Na GPU simplificada, cada núcleo processa um bloco por vez e tem ALU, LSU, PC e arquivo de registradores dedicados para cada thread do bloco
  • O escalonador gerencia a execução das threads e não seleciona um novo bloco antes de concluir o bloco atual
  • O fetcher busca instruções de forma assíncrona a partir do contador de programa atual
  • O decodificador decodifica as instruções buscadas em sinais de controle para a execução das threads
  • Cada thread tem seu próprio conjunto dedicado de arquivos de registradores
  • A ALU é uma unidade lógico-aritmética dedicada por thread
  • A LSU é uma unidade de load-store dedicada por thread para acessar a memória global de dados
  • O PC é um contador de programa dedicado que determina a próxima instrução a ser executada em cada thread

ISA

  • Implementa uma ISA simples com 11 instruções
  • Construída para kernels simples, como adição e multiplicação de matrizes
  • Suporta operações aritméticas básicas, load/store de memória, desvios, carregamento de constantes etc.

Execução

  • Cada núcleo passa pelos estágios de busca, decodificação, requisição, espera, execução e atualização para executar instruções
  • Cada thread segue um caminho de execução para realizar cálculos sobre os dados no arquivo de registradores
  • Para funcionalidade SIMD, há valores de índice de bloco, dimensão e índice de thread em registradores somente leitura

Kernel

  • Kernels de adição e multiplicação de matrizes foram escritos na ISA para demonstrar programação SIMD e execução em GPU
  • Com os arquivos de teste, é possível simular completamente a execução dos kernels na GPU e gerar o estado da memória de dados e o rastreamento da execução

Simulação

  • Depois de instalar iverilog e cocotb, é possível executar a simulação do kernel com o comando make
  • O arquivo de log exibe o estado inicial/final da memória de dados e o rastreamento completo da execução do kernel

Recursos avançados

  • Muitos recursos adicionais das GPUs modernas que melhoram bastante o desempenho e a funcionalidade foram omitidos para simplificação
  • São discutidos recursos como cache multinível e memória compartilhada, coalescência de memória, pipelining, escalonamento de warp, divergência de desvios, sincronização e barreiras

Opinião do GN⁺

  • Explica muito bem, de forma simples e fácil de entender, os principais conceitos da arquitetura de GPU e do modelo de programação SIMD. Em especial, mostra claramente como o processamento paralelo acontece em uma GPU real por meio de exemplos de kernels de operações com matrizes.
  • Os recursos avançados usados em GPUs modernas também estão bem organizados, então, depois de entender a tiny-gpu, isso deve ajudar no estudo de arquiteturas de GPU mais complexas.
  • No entanto, como os recursos do pipeline gráfico propriamente dito não estão incluídos, não aborda como funciona o hardware especializado em gráficos. Para quem tem interesse em gráficos, isso pode deixar a desejar.
  • Comparar com outras arquiteturas de GPU open source, como MIAOW ou GPGPU-Sim, também parece útil para entender GPUs mais realistas.
  • Se no futuro forem adicionados recursos como divergência de desvios, coalescência de memória e pipelining, a expectativa é que se torne um material de aprendizado ainda mais prático. O fato de ser um projeto open source ao qual se pode contribuir também é atraente.

1 comentários

 
GN⁺ 2024-04-27
Comentários do Hacker News
  • A Intel publica muita documentação técnica sobre GPUs. Também é possível encontrar online os manuais do 810/815. Com exceção do 855/910/915/945, a documentação tem sido feita de forma consistente.

  • Incentiva trabalhos com GPUs de núcleo aberto.

  • Há outro projeto de GPU open source chamado NyuziProcessor. (https://github.com/jbush001/NyuziProcessor)

  • Quero começar com FPGA, mas é difícil entender por onde começar, e a área em si parece intimidadora.

  • O objetivo final é criar uma placa aceleradora para LLM (Large Language Model). Tirando a parte de offloading de memória, provavelmente haverá muitos pontos em comum com este projeto.

  • Pergunta por que são misturados operadores de atribuição non-blocking e blocking em blocos always sequenciais.

  • Já fez algo parecido em VHDL no passado. Havia vários projetos HDL open source no site opencores. Fica a dúvida se hoje existe algum simulador HDL distribuído em grande escala, em nível de HPC. Faz sentido usar GPUs modernas para executar simulação em nível de RTL.

  • Gosta de ver projetos de hardware sendo abertos. Mas isso poderia ser chamado de coprocessador SIMD. Para ser uma GPU, precisaria ter pelo menos algum tipo de saída de vídeo. Recentemente, Nvidia e outras passaram a vender variantes de arquitetura gráfica voltadas só para servidores como GPU, então o termo ficou um pouco mais flexível, mas a parte "gráfica" do projeto de uma GPU ainda responde por boa parte da complexidade.

  • Questiona se é comum que a ALU implemente diretamente a instrução DIV em hardware. Fica a dúvida se isso é realmente usado como instrução em algo como núcleos CUDA modernos, ou se normalmente é emulado por software. Um circuito real de divisão em hardware ocupa muito espaço, então não era algo esperado em ALUs de GPU. Em Verilog, é fácil escrever DIV: begin alu_out_reg <= rs / rt; end, mas em silício isso consome bastante área. Quem só simula Verilog pode não perceber isso.

  • Outra "GPU" que não oferece recursos gráficos. Na opinião da pessoa, essas coisas deveriam ser chamadas por outro nome.

  • O projeto simplificou assumindo que as threads são processadas em paralelo e que, após cada instrução, todas "convergem" para o mesmo contador de programa. Em GPUs reais, threads individuais podem desviar para PCs diferentes, causando branch divergence. Seria melhor programar GPU antes de tentar construir uma em silício. Nem isso é SIMD. (A mesma pessoa que montou um circuito para piscar LED e disse que tinha feito uma CPU)