1 pontos por GN⁺ 5 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • nbd-vram é um pequeno daemon que permite usar a VRAM ociosa de uma GPU NVIDIA no Linux como espaço de swap de alta prioridade
  • Em notebooks com gráficos híbridos, onde a memória é soldada e difícil de expandir e a GPU integrada AMD/ATI cuida da saída de vídeo, ele aproveita a VRAM NVIDIA que ficaria ociosa para aliviar a pressão de memória
  • O ambiente de teste foi AMD/ATI + RTX 3070 Laptop, RAM de 16GB, VRAM de 8GB, driver NVIDIA 580.159.03, kernel 6.17 e Pop!_OS; com 7GB de VRAM alocados como swap, somando também zram e swap em SSD, o sistema chega a cerca de 46GB de memória endereçável
  • A ordem de funcionamento é: a RAM enche primeiro, depois a VRAM absorve as páginas excedentes via PCIe, em seguida o zram faz compressão na CPU e, por fim, usa-se o SSD
  • O daemon aloca VRAM pela CUDA driver API e fornece um dispositivo de bloco pelo protocolo NBD (Network Block Device) sobre um socket Unix; o driver nbd embutido no kernel o expõe como /dev/nbdX, permitindo uso como um dispositivo de swap comum
  • O caminho dos dados é kernel swap subsystem → /dev/nbdX → nbd kernel driver → Unix socket → nbd-vram daemon → cuMemcpyHtoD/DtoH → VRAM da GPU
  • Não são necessários módulo de kernel separado nem símbolos de kernel da NVIDIA, então a solução pode continuar funcionando após atualizações de kernel e driver sem precisar recompilar
  • A abordagem com a API NVIDIA P2P falha em GPUs GeForce de consumo porque nvidia_p2p_get_pages_persistent retorna EINVAL, e a abordagem de ioremap_wc direto no BAR1 também falha, retornando 0 na leitura de áreas fora de cerca de 16MiB do framebuffer de exibição
  • O caminho de cópia via CUDA, com cuMemcpyHtoD e cuMemcpyDtoH, funciona em GPUs CUDA sem privilégios especiais, então o acesso por NBD contorna as limitações de P2P e BAR1
  • Os requisitos são GPU NVIDIA com suporte a CUDA, driver NVIDIA com libcuda.so.1, módulo nbd do Linux kernel 3.0+, nbd-client, gcc e make; o CUDA toolkit não é necessário
  • Após a instalação, o serviço systemd vram-swap-nbd é executado automaticamente na inicialização, e é possível ajustar o limite máximo de VRAM usada e a prioridade do swap com VRAM_SETUP_SIZE_MB e VRAM_SWAP_PRIORITY em /etc/systemd/system/vram-swap-nbd.service
  • O daemon tenta primeiro o tamanho de VRAM solicitado e, se faltar memória na GPU, reduz a alocação em blocos de 512MiB; assim, VRAM_SETUP_SIZE_MB funciona como limite superior, não como tamanho obrigatório
  • Se o gerenciamento com reconhecimento de energia estiver ativado, o serviço para automaticamente ao desconectar da energia AC ou ao ficar abaixo do limite de bateria, e reinicia quando a energia volta; um systemctl stop manual não é sobrescrito
  • No benchmark com RTX 3070 Laptop, a NVMe é mais rápida em throughput sequencial e I/O aleatório sustentado, mas na latência de leitura 4K com 1 request/sec a VRAM teve média de 335us, 27 vezes mais rápida que os 9.05ms da NVMe
  • É distribuído sob a licença MIT, e o repositório inclui test-nbd.sh para smoke test, test-fill.sh para verificação de partição completa e scripts de benchmark de throughput, IOPS e latência

1 comentários

 
GN⁺ 5 시간 전
Comentários no Hacker News
  • Se fosse tratado via CUDA como armazenamento de arquivos ou algo montável, o overhead seria alto; usando BAR, parece que daria para melhorar bastante a taxa de transferência e os IOPS

  • Se a explicação é que isso serve para notebooks com memória soldada, sem caminho de upgrade, então responde à dúvida imediata de por que usar swap de uma RAM cara para uma RAM ainda mais cara
    O caso de uso parece limitado, mas usar 8GB de VRAM ociosa quando o sistema está fazendo swap para SSD parece uma boa ideia quando necessário

    • Outro motivo é que às vezes você tem VRAM, mas não a usa o tempo todo
      Por exemplo, se você comprou a GPU para jogar, quando não está jogando não precisa de 16GB de VRAM para renderizar o desktop, então talvez faça sentido usar para outra coisa
      Mas isso pressupõe que, ao iniciar um jogo, o sistema consiga liberar a VRAM que estava sendo usada como swap; fico curioso se isso é realmente possível
    • Dá para usar VRAM de fato como se fosse RAM comum? Por exemplo, se houver um módulo de 16GB de RAM e a GPU tiver 16GB de VRAM, dá para fazer o sistema aparecer com 32GB de RAM, e quais seriam os impactos?
    • Antigamente isso era chamado de RAM disk, e no Atari ST ficava absurdamente rápido
      No Amstrad PCW, comum no Reino Unido de meados dos anos 80 até meados dos 90, dava para usar até 512kB de RAM, e uma parte considerável disso podia virar RAM disk
      Compilar em Turbo Pascal também ficava muito rápido :-)
  • A ideia é boa, mas parece haver algo muito errado aqui
    Dizem que no RTX 3070 Laptop a taxa sequencial é de cerca de 1.3 GB/s, mas esse chip RTX 3070 é PCIe 4.0 x16, então deveria dar 64GB/s, e os próprios 8GB de GDDR6 têm 448GB/s
    Fazer swap para um drive NVMe provavelmente seria duas vezes mais rápido, embora com latência maior

    • PCIe 4.0 x16 é 32 GB/s por direção, e essa implementação não é o tipo de abordagem que se escolhe quando se quer alto desempenho
      O benchmark também foi feito com ZRAM, e o ZRAM comprime as páginas antes de gravá-las no swap. Não sei exatamente qual é o overhead disso, mas há uma boa chance de ser significativo
      Primeiro, o programa em espaço de usuário fica preso ao driver nbd, que é conhecido por ser lento, e ainda usa um bounce buffer em espaço de usuário antes de transferir para a GPU. Quando o kernel precisa fazer swap de uma página, ele primeiro copia para um buffer exposto ao espaço de usuário, depois o programa em espaço de usuário precisa acordar de novo e emitir a operação CUDA para copiar essa página para a memória do dispositivo
      O nbd também não lida bem com alta profundidade de fila nem com fusão de acessos adjacentes. Se o kernel emitir muitos swaps de páginas de 4K sem fusão, só para sustentar 4 GB/s já seriam necessárias pelo menos um milhão de trocas de contexto kernel/usuário por segundo. 64 GB/s então nem se fala. E isso olhando só para a parte do NBD, sem contar a complexidade do driver da NVIDIA
      O PCIe consegue mover muitos dados, mas para chegar perto da largura de banda total você precisa usar um motor de DMA com listas longas de páginas. Se você configurar uma transferência para cada página de 4K no PCIe, não vai conseguir saturar completamente o barramento
      O caminho de swap para NVMe é altamente otimizado. O swaper pode enviar diretamente listas de páginas ao driver NVMe, e o controlador as busca diretamente da RAM via DMA, sem nenhuma cópia do lado da CPU nem troca de contexto
      Talvez migrando para o driver ublk dê para evitar o bounce buffer em espaço de usuário, e também seria possível configurar em paralelo cópias CUDA com várias filas de escrita, o que pode melhorar
    • Fazer swap para NVMe também consome ciclos de PE do NAND, causando desgaste ao longo do tempo
      RAM e VRAM não se degradam por serem usadas
  • Tenho uma máquina de desenvolvimento com 32GB de RAM e 32GB de VRAM que fica majoritariamente ociosa quando não estou rodando modelos de IA, então essa ideia não parece tão ruim

    • Isso passa uma sensação meio pcmasterrace de corpo com tronco enorme e pernas fininhas
  • Fico pensando como isso lida com backpressure. O que acontece se surgir uma demanda de alocação de VRAM enquanto a VRAM está sendo usada como espaço de swap?
    No X11, os buffers já são pré-alocados, então não é tão ruim, mas no Wayland as alocações são muito mais dinâmicas, então se a VRAM acabar o desktop inteiro pode morrer facilmente
    Já tive alguns travamentos assim ao alternar a máquina entre Hyprland+llama-server+KVM, sem conseguir liberar a VRAM

  • Criar um dispositivo de swap em nível de usuário sempre foi um daqueles problemas clássicos supostamente insolúveis
    Se o daemon precisa fazer swap-in de uma página, mas para fazer isso antes precisa fazer swap-in das próprias páginas do daemon, o que acontece?
    Pelo menos havia esse tipo de discussão como motivo de microkernels nunca poderem funcionar de verdade. Não entendo bem qual é a solução aqui

    • Basta o daemon ser inteligente o suficiente para saber quais são as próprias páginas e impedir que elas sejam swapadas
      O kernel do Linux também impede que suas próprias páginas de texto sejam swapadas, então a solução já existe, e não vejo por que ela não se aplicaria a projetos de microkernel
    • O princípio geral é que aquilo que participa da paginação não pode, ele próprio, ser paginado
      Se você travar toda a memória desse daemon, o problema fica resolvido de forma trivial
  • Lembro de ter feito algo parecido no passado com o driver MTD/phram do Linux: https://wiki.archlinux.org/title/Swap_on_video_RAM
    Só não sei se ainda é relevante hoje, porque não sei como isso interage com DRM nem como se faz a reserva de uma parte da VRAM. A sugestão de limitar via xorg.conf provavelmente já está bem ultrapassada
    Nessa página também há um sistema de arquivos FUSE implementado sobre OpenCL: https://github.com/Overv/vramfs
    Talvez esse tenha melhor compatibilidade

    • Antigamente eu mapeava 8MB de memória de vídeo via mtd e usava assim, e isso ajudava a compilar aqueles... drivers X11
      Dá até nostalgia
  • Também vi algo parecido no Windows alguns anos atrás
    Era um driver experimental de prova de conceito que permitia criar um RAM drive com a VRAM de placas NVIDIA, e o acesso sequencial era rápido como esperado, embora o acesso aleatório ainda tivesse bastante espaço para melhorar
    GpuRamDrive cria um drive virtual sustentado por RAM da GPU: https://github.com/prsyahmi/GpuRamDrive
    Fork com suporte a AMD: https://github.com/brzz/GpuRamDrive/

  • É parecido, mas usa a API OpenCL, então também funciona em AMD
    Só que o driver da AMD é bem bugado, então é preciso definir o que significa “funcionar”: https://libguestfs.org/nbdkit-vram-plugin.1.html

  • Não entendo por que um Mac Apple Silicon com 32GB de RAM, ainda com 20GB não usados/“free”, usa ou até cria arquivo de swap
    Por que não existe algo tão simples quanto swapoff -a no Linux para desativar completamente o arquivo de swap?
    A menos que a ideia seja reduzir deliberadamente a vida útil do SSD, isso parece meio bobo
    Seria bom haver uma configuração no GUI para desligar o arquivo de swap, e a Apple também poderia finalmente abandonar a atual “etapa” de layout/configurações do sistema. Comparado com décadas de painéis de preferências, ainda parece uma salada de palavras
    #Apple #Feedback #swapfile

    • O princípio dos sistemas de paginação é que a memória principal é o cache do armazenamento secundário
      Até o conceito de “memória disponível” idealmente é mais próximo de “memória que pode ser recuperada rapidamente para outro propósito”
      Em certos momentos, pode ser melhor deixar conteúdo de arquivos em cache ocupar esse espaço do que manter memória anônima na memória principal continuamente