AMD recupera até 95% do desempenho de GPU no Linux em VMs KVM com novo batch userptr no amdkfd

Uma nova IOCTL batch no amdkfd troca pinning por HMM e devolve performance “quase nativa” para workloads de IA dentro de guests KVM.

Escrito por
Emanuel Negromonte
Emanuel Negromonte é Jornalista, Mestre em Tecnologia da Informação e atualmente cursa a segunda graduação em Engenharia de Software. Com 14 anos de experiência escrevendo sobre...

A AMD publicou uma série de patches (v2, 0/4) para o amdkfd que mira diretamente um gargalo clássico de virtualização: o custo de registrar milhares de pedaços de memória espalhados, um por um, dentro de um guest KVM.

Nos números reportados na própria série, a mudança sai de um cenário em que a performance despenca para ~80.000 pontos (vs ~200.000 no bare metal) e chega a 160.000–190.000, recuperando até 95% do desempenho “quase nativo”. O ganho declarado fica entre 2x e 2,4x contra a solução alternativa em userspace.

Entenda em 90 segundos

Em VMs, o padrão de alocação de memória costuma ficar mais “quebrado”: em vez de um bloco grande e contínuo, a aplicação frequentemente termina com milhares de ranges não contíguos de VA da CPU.

No método antigo (workaround em userspace), cada pedaço exigia uma “viagem” separada ao kernel para registrar o range via IOCTL, repetindo o custo de syscalls.

A analogia visual: imagine um correio entregando 1000 cartas, indo e voltando uma por uma (approach antigo), versus entregar um malote consolidado com tudo de uma vez (approach batch no kernel). O conteúdo é o mesmo, o custo logístico não.

O problema na prática: syscall hell

A própria descrição do patch aponta um padrão comum em workloads modernos: alocações “scattered” vindas de malloc() podem gerar de 2 até 4000+ ranges.

Quando o processo tenta registrar esses ranges individualmente no guest KVM usando múltiplas chamadas à IOCTL existente AMDKFD_IOC_ALLOC_MEMORY_OF_GPU, o custo acumulado de syscalls vira o gargalo.

Os números compartilhados a lista do kernel resumem bem o impacto:

  • Bare metal (baseline): ~200.000
  • Workaround em userspace (múltiplas IOCTLs): ~80.000
  • Perda reportada: 60% de degradação
  • Com batch no kernel: 160.000–190.000
  • Recuperação: 80%–95% do bare metal

Deep dive técnico: HMM vs. pinning

A v2 é, por intenção, um “reset” conceitual em relação à v1. A primeira tentativa tentou resolver via SVM e acabou esbarrando em consequências indesejadas para paginação e gerenciamento de memória.

Por que a v1 falhou, segundo a própria série

A v1 propunha:

  • Nova IOCTL: AMDKFD_IOC_SVM_RANGES
  • Atributo: KFD_IOCTL_SVM_ATTR_MAPPED para VMA especial
  • Fixação de páginas: pin_user_pages_fast()

E lista problemas diretos desse caminho:

  • O pinning “derrotava” o propósito de SVM com HMM, que depende de paginação sob demanda.
  • Bloqueava oversubscription e migração dinâmica.
  • Podia gerar pressão de memória por páginas travadas.
  • Interferia com otimizações de NUMA e migração.

O que a v2 faz diferente

A v2 desloca a solução para a infraestrutura já existente de userptr, estendendo o caminho de ALLOC_MEMORY_OF_GPU em vez de mexer no SVM, e introduz a nova IOCTL:

  • AMDKFD_IOC_ALLOC_MEMORY_OF_GPU_BATCH

A promessa técnica central é: “sem pinning”. Em vez de travar páginas, a v2 usa HMM para rastrear e validar páginas, mantendo a capacidade de páginas serem swapadas ou migradas quando não estão em uso.

Os pontos de implementação destacados no texto-fonte:

  • Um mmu_interval_notifier por range de CPU VA, para invalidação por intervalo.
  • Todos os ranges são validados em conjunto e mapeados para um GPU VA contíguo.
  • Um único objeto kgd_mem, contendo um array de user_range_info, para rastrear múltiplos ranges em uma alocação.
  • Caminho unificado de eviction/restore para o batch.

Modelo mental: muitos VAs de CPU viram um VA de GPU

A série descreve exatamente este remapeamento como o “encaixe” do userptr:

  • Entrada: vários ranges de CPU VA não contíguos.
  • Saída: um único range de GPU VA contíguo.

Em outras palavras, a GPU enxerga uma janela linear, enquanto a CPU continua vivendo com o layout fragmentado típico do processo no guest. O batch serve para registrar esse “mosaico” sem pagar a tarifa de syscall em cada ladrilho.

Contexto de mercado e workloads

O texto-fonte posiciona a mudança como relevante para cenários de IA em virtualização, incluindo workloads e testes específicos:

  • Stable Diffusion e ComfyUI em ambientes virtualizados
  • Inferência de LLMs 3B–7B com HuggingFace transformers
  • OpenCL CTS e HIP catch tests em KVM guest

Há também um ponto arquitetural importante para infraestrutura: ao evitar pinning e usar HMM, a abordagem preserva propriedades necessárias para ambientes com pressão de memória, como eviction/restore e a possibilidade de páginas serem migradas.

O texto-fonte conecta isso diretamente a um objetivo operacional: evitar que a otimização de GPU em VM force páginas a ficarem permanentemente travadas, algo que dificultaria oversubscription e migração dinâmica.

O que muda para quem usa

Se você roda workloads de GPU em guest KVM, a série descreve impactos práticos na forma como o registro de memória “scattered” pode ser feito:

  • Reduz o overhead de syscalls ao registrar ranges não contíguos em batch via AMDKFD_IOC_ALLOC_MEMORY_OF_GPU_BATCH.
  • Recupera performance em virtualização, nos números reportados, para a faixa de 80%–95% do bare metal.
  • Evita pinning de memória, mantendo páginas swapáveis/migráveis sob HMM.
  • Unifica o gerenciamento de múltiplos ranges em um único kgd_mem com user_range_info.
  • Mantém invalidação por range via mmu_interval_notifier, alinhada ao modelo de consistência do userptr.

Pontos explícitos que não aparecem na fonte e, portanto, ficam fora do escopo factual:

  • Requisitos de configuração específicos (QEMU, VFIO, passthrough, flags): [NÃO INFORMADO NA FONTE]
  • GPUs e SKUs impactadas, ou versões mínimas de ROCm/kernel necessárias: [NÃO INFORMADO NA FONTE]
  • Prazo de merge, árvore alvo, ou presença em releases do kernel: [NÃO INFORMADO NA FONTE]

Mini-glossário

  • Userptr: modelo em que o driver trabalha com ponteiros para endereços do espaço de usuário, permitindo remapeamento de VA de CPU para VA de GPU.
  • HMM (Heterogeneous Memory Management): infraestrutura do kernel para rastreamento e integração de memória entre CPU e dispositivos, apoiando paginação sob demanda.
  • IOCTL: chamada de controle entre userspace e kernel para executar operações específicas de um driver.
  • Syscall overhead: custo de transição userspace→kernel, que se torna relevante quando repetido milhares de vezes.
  • KVM guest: sistema operacional convidado rodando sob o hypervisor KVM.
Compartilhe este artigo