15 pontos por GN⁺ 2026-02-23 | 1 comentários | Compartilhar no WhatsApp
  • Motor de inferência de LLM em C++/CUDA que permite executar o modelo Llama 70B em uma RTX 3090 (24 GB de VRAM) por meio de streaming da memória da GPU e E/S direta opcional com NVMe
  • Usa uma estrutura de cache adaptativo em 3 camadas para dividir automaticamente entre VRAM, RAM fixa e fallback em NVMe/mmap, alcançando até 83x mais velocidade em relação ao mmap
  • O backend gpu-nvme-direct transfere dados diretamente do NVMe para a GPU, contornando completamente a CPU e aproveitando ao máximo a largura de banda do PCIe
  • Recursos de layer skip e self-speculative decoding reduzem computações desnecessárias e aumentam a velocidade de processamento sem perda de qualidade
  • Permite rodar modelos extremamente grandes com eficiência em hardware de consumo, apontando para uma maior acessibilidade à inferência de LLMs de alto desempenho

Visão geral do NTransformer

  • Motor de inferência de LLM de alta eficiência em C++/CUDA que executa o modelo Llama 70B em uma RTX 3090 (24 GB de VRAM)
    • Faz streaming das camadas do modelo pela memória da GPU e, opcionalmente, usa E/S direta com NVMe para contornar completamente a CPU
  • Sem dependências externas além do CUDA Toolkit; não requer PyTorch nem cuBLAS
  • Suporta o formato de modelo GGUF, com quantizações Q4_0, Q8_0, Q4_K_M, Q5_K, Q6_K, F16 e F32

Desempenho e estrutura de cache

  • Cache adaptativo em 3 camadas (3-Tier Adaptive Caching)
    • Camadas residentes na VRAM (0 E/S)
    • RAM fixa (somente para transferência H2D)
    • Fallback em NVMe/mmap
  • Em um ambiente com RTX 3090 + 48 GB de RAM, obteve 83x mais velocidade em relação ao mmap
  • A largura de banda do PCIe Gen3 x8 (cerca de 6,5 GB/s) atua como gargalo
  • A quantização Q4_K_M carrega 10 camadas a mais na VRAM (36 vs 26), reduzindo o volume de transferência
  • O layer skip (baseado em similaridade de cosseno) pula 20 de 80 camadas, com perda mínima de qualidade

Principais recursos

  • Streaming SLEP: sobreposição de leitura NVMe, DMA via PCIe e computação na GPU com buffer duplo
  • Backend gpu-nvme-direct: lê dados do NVMe diretamente para memória fixa acessível pela GPU
  • Self-speculative decoding: usa as camadas residentes na VRAM como modelo de rascunho, sem necessidade de modelo adicional
  • Seleção automática do caminho de dados: residente na VRAM > RAM fixa H2D > mmap fixo > memcpy da CPU
  • Suporte à arquitetura Llama: inclui RoPE, GQA, SwiGLU, RMSNorm e cache KV

Requisitos do sistema

  • Linux (Ubuntu, kernel 6.17+), CUDA Toolkit 13.1, gcc/g++ 14, CMake 3.24+
  • GPU com Compute Capability 8.0+ (RTX 3090 testada)
  • Para usar E/S direta com NVMe, é necessário um SSD NVMe em slot PCIe separado e a biblioteca gpu-nvme-direct

Streaming direto NVMe

  • Quando o modelo não cabe na VRAM, usa-se um caminho direto NVMe → GPU, excluindo completamente a CPU
    • Fluxo de dados: NVMe SSD → DMA → memória de staging fixa → PCIe H2D → buffer da GPU → computação
  • O NVMe é vinculado ao VFIO para acesso direto em espaço de usuário
  • Cada camada (cerca de 670 MB no caso de um 70B Q6_K) é lida em cerca de 202 ms com 670 comandos NVMe
  • Leitura NVMe, DMA H2D e computação na GPU são processados em paralelo em um pipeline de buffer duplo

Configuração do sistema e avisos de risco

  • O script de configuração automática (setup_system.sh) configura em sequência GRUB, NVIDIA DKMS, cabeçalhos CUDA, VFIO e binding do NVMe
  • Inclui operações de alto risco, como desativação de IOMMU, patch em módulos do kernel e binding de NVMe ao VFIO
  • Configurações incorretas podem causar falha de boot, perda de dados no NVMe e instabilidade do sistema
  • Nunca use a unidade de boot; é necessário um dispositivo NVMe dedicado e separado
  • Todas as alterações contam com scripts de backup e restauração

Arquitetura e estrutura do código

  • Principais componentes no diretório src/
    • core/: tensores, alocação de memória, gerenciamento de dispositivo GPU
    • cuda/: kernels de GEMV, RMSNorm, RoPE, SwiGLU e softmax
    • memory/: motor de streaming SLEP baseado em NVMe e mmap
    • model/: composição do Transformer, loader GGUF, attention, FFN, normalization
    • inference/: tokenizador, sampler, motor
  • scripts/: inclui scripts de configuração do sistema, binding de NVMe e restauração

Roadmap por etapas de desenvolvimento

  • Etapa 1: Llama 8B Q8_0, kernels CUDA customizados, 48,9 tok/s (concluída)
  • Etapa 2: streaming SLEP, execução de 70B em uma única GPU, ganho de 33x em velocidade (concluída)
  • Etapa 3: suporte a Q4_K_M/Q5_K, layer skip, self-speculative decoding, cache KV em F16 (concluída)
  • Etapa 4: backend NVMe Direct, leitura NVMe guiada pela GPU a 3,35 GB/s (concluída)
  • Etapa 5: otimização da inferência e API C pública (planejada)

Licença

  • Licença BSD-2-Clause

1 comentários

 
GN⁺ 2026-02-23
Comentários do Hacker News
  • Acho realmente inteligente a abordagem de transferir diretamente do NVMe para a GPU, contornando a CPU
    Ao rodar modelos grandes localmente, o gargalo sempre foi a hierarquia de memória, e isso basicamente trata o NVMe como uma VRAM estendida, acessada diretamente via DMA
    Fico curioso sobre como isso se compararia à abordagem de memória unificada (unified memory) da série Apple M. O M4 Max consegue colocar um modelo 70B inteiro na memória, mas o throughput é menor que o de uma 3090
    Seria interessante ver um benchmark comparando o desempenho nativo da 3090 com essa abordagem via NVMe e do M4 Max com base em inferência em lote (batch inference)

    • Tenho um M3 e pretendo testar no Metal
  • Com GPUdirect, é possível fazer transferência DMA direta para dispositivos de armazenamento
    Fiquei pensando em como seria se o armazenamento m.2 fosse, na prática, DRAM. Ao fazer spill do modelo a partir da GPU, não há necessidade de persistência, então a RAM do sistema poderia ficar disponível para a CPU

    • Usar um RAM disk provavelmente seria muito melhor. É uma pena que o Intel Optane não tenha virado padrão. Era uma tecnologia perfeita para esse tipo de workflow
    • Pensei a mesma coisa. Há algum tempo apresentei no Dask Summit sobre dask-cudf, acelerando análise de logs com uma arquitetura de array paralelo de SSDs → GPUDirect Storage → PCIe → GPU A100. Hoje seria interessante aplicar essa estrutura a LLMs ou modelos MoE
    • Na verdade, armazenamento m.2 baseado em DRAM já existe na forma de CXL (Compute Express Link). O problema é que a RAM é cara demais, então é difícil aproveitar a largura de banda de 31GB/s por conector NVMe
  • Uma velocidade de 0.2 token/s é lenta para chat, mas suficiente para tarefas em lote/assíncronas
    Eu executo pipelines de geração automática de conteúdo, com várias chamadas de LLM em paralelo. A geração de imagens é o gargalo, então o trabalho inteiro já leva uns 20 minutos de qualquer forma
    Se eu pudesse rodar um modelo 70B localmente, isso economizaria custos com tokens de API e seria uma grande redução de custo

    • Em termos de custo, isso não é eficiente. Com 0.5 tok/s, são 3600 tokens por hora, e um sistema com 3090 consome 200~300W. Para essa mesma quantidade de tokens, usar llama 3.1 via OpenRouter sai muito mais barato que a conta de luz. Ainda assim, faz sentido do ponto de vista de inferência privada
    • Também é preciso considerar o custo de energia de manter uma 3090 rodando a 350W por longos períodos
  • 0.2 tok/s é aceitável para experimentação, mas insuficiente para uso interativo
    Na maioria dos casos, modelos 8B ou 13B bem quantizados oferecem um equilíbrio melhor entre latência e qualidade

    • Eu só queria testar se era possível. No passado, consegui 3000 tokens por segundo em um transformer clássico no PS2, graças a uma arquitetura que envia comandos diretamente da memória para a GPU. PCs comuns são lentos porque precisam passar pela CPU. GPUs profissionais resolvem esse problema, mas são caras demais
    • Ainda assim, em certas situações, a qualidade de modelos grandes pode ser mais importante
    • Rodar com uma combinação CPU+GPU é mais rápido. Eu consigo cerca de 1.5 tok/s com um 7950X+3090
    • Só depois de ver a tabela de desempenho percebi que a entrada do topo era um modelo 8B. 5 segundos por token é lento demais. No meu sistema com 5950X+128GB RAM, a combinação de CPU com GPU 3060 provavelmente seria mais rápida. Também não acho muito convincente a afirmação de que 2 segundos por token seja o limite computacional de uma 3090
  • Experimento realmente interessante. Eu deveria ter tentado algo assim antes
    Queria saber os números reais de throughput em relação à largura de banda teórica do PCIe. Gostaria de entender se isso é um problema de latência ou de largura de banda

    • Na prática, é um gargalo de largura de banda. Minha placa-mãe B450 só suporta PCIe3 x8, então a GPU fica limitada. Se eu fizer upgrade para X570, a velocidade deve aumentar de 2 a 3 vezes
  • É um hack muito legal, mas 0.5 tok/s em um modelo 70B é lento em comparação com os 30+ tok/s que a mesma placa entrega em um modelo 7B
    Segundo pesquisas da NVIDIA, modelos abaixo de 10B já conseguem lidar com 40~70% das tarefas de agentes, e a diferença de qualidade está diminuindo rapidamente

  • Essa área ainda vale muito a pena para experimentação
    No longo prazo, parece que o essencial será a otimização dos modelos, ou seja, pesquisar quais partes do modelo podem ser omitidas sem afetar o desempenho. No fim das contas, o modelo também é uma forma de compressão com perdas (lossy compression). Esse caminho também ajudaria na democratização da IA

    • A analogia com compressão é interessante. Fine-tuning também pode ser visto assim. Por exemplo, se você ajustar um modelo 3B para uma tarefa específica, deixa de precisar da generalidade de um modelo 70B
  • Projeto realmente incrível. Fico curioso sobre que tipo de conhecimento de sistemas/hardware é necessário para ter uma ideia dessas
    Eu trabalho em ambientes onde o hardware é muito abstraído, então é difícil imaginar esse tipo de abordagem. Parece exigir não só criatividade, mas também entendimento em nível de sistema

    • Esse foi exatamente o experimento: projeto ps2-llm
      Ao tentar rodar um LLM no PS2, bati no limite de 32MB de RAM e 4MB de VRAM, então criei um método de streaming de camadas. O PS2 conseguia lidar diretamente com endereços de 32 bits na VRAM, então era muito rápido, e tentei reproduzir isso também no PC
    • Penso de forma parecida. Nos consoles antigos, a CPU era lenta, então a transferência DMA era essencial. Provavelmente essa experiência levou a essa ideia. O smart memory card do PS2 também tinha um DMA bem complexo
  • Também estou tentando algo parecido. Estou experimentando rodar um modelo 1T usando menos da metade da VRAM
    Acho que, modificando a camada de roteamento do SGLang, dá para implementar expert swap baseado em previsão JIT da Gen5 NVMe para a memória da GPU. Estou usando primitivas NVIDIA Dynamo e NIXL
    Queria saber se alguém já tentou isso

    • Eu também gostaria de ver isso. Estou pensando em comprar outra 3090 e fazer um upgrade da placa-mãe para resolver o gargalo do PCIe3. Talvez dê para rodar glm 4.7~5 em q4_k_m
  • Projeto muito legal. Gostaria de saber mais detalhes sobre o processo de patch DKMS em GPUs comuns. Também quero tentar

    • Atualizei a documentação para incluir o processo de patch e as informações de risco
    • Também houve casos em que modificaram o driver open source da NVIDIA para desbloquear recursos corporativos como comunicação P2P entre GPUs ou particionamento vGPU
      Links relacionados: RTX4090 P2P Unlock, vGPU Unlock