O nVidia RDMA GPUDirect sempre opera apenas endereços físicos (no espaço de endereço físico da CPU)?

StackOverflow https://stackoverflow.com/questions/19841815

Pergunta

Como sabemos: http://en.wikipedia.org/wiki/IOMMU#Advantages

A paginação de memória periférica pode ser suportada por um IOMMU.Um periférico utilizando o PCI-SIG PCIe Address Translation Services (ATS) Page Request A extensão da interface (PRI) pode detectar e sinalizar a necessidade de memória serviços de gestão.

enter image description here

Mas quando usamos GPU nVidia com CUDA >= 5.0, podemos usar RDMA GPUDirect e saber que:

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#how-gpudirect-rdma-works

Tradicionalmente, os recursos como as janelas BAR são mapeados para o utilizador ou para o kernel espaço de endereçamento utilizando a MMU da CPU como memória mapeada I/O (MMIO) Endereços.No entanto, porque Os sistemas operacionais atuais não têm mecanismos suficientes para trocar regiões MMIO entre drivers, o NVIDIA kernel driver exporta funções para executar o necessário Traduções e mapeamentos de endereços.

http://docs.nvidia.com/cuda/gpudirect-rdma/index.html#supported-systems

RDMA para GPUDirect atualmente depende de todos os endereços físicossendo o mesmo do ponto de vista dos dispositivos PCI.Isto faz com que incompatíveis com IOMMUs e, portanto, eles devem ser desactivados para RDMA para GPUDdirect para trabalhar.

E se alocarmos e mapearmos CPU-RAM para UVA, como aqui:

#include <iostream>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

int main() {
    // Can Host map memory
    cudaSetDeviceFlags(cudaDeviceMapHost);  

    // Allocate memory
    unsigned char *host_src_ptr = NULL;
    cudaHostAlloc(&host_src_ptr, 1024*1024, cudaHostAllocMapped);
    std::cout << "host_src_ptr = " << (size_t)host_src_ptr << std::endl;

    // Get UVA-pointer
    unsigned int *uva_src_ptr = NULL;
    cudaHostGetDevicePointer(&uva_src_ptr, host_src_ptr, 0);
    std::cout << "uva_src_ptr  = " << (size_t)uva_src_ptr << std::endl;

    int b;  std::cin >> b;
    return 0;
}

Obtemos ponteiros iguais em Windwos7x64, o que significa que cudaHostGetDevicePointer() fazer nada:

host_src_ptr=68719476736

uva_src_ptr = 68719476736

O que significa "mecanismos suficientes para troca de regiões MMIO entre drivers", qual mecanismo se entende aqui e por que não consigo usar IOMMU usando o endereço virtual para acessar via PCIe à região física do BAR - outro dispositivo mapeado em memória via PCIe ?

E isso significa que o RDMA GPUDirect sempre opera apenas endereços físicos (no espaço de endereço físico da CPU), mas por que enviamos para a função do kernel uva_src_ptr que é igual a host_src_ptr - ponteiro simples no espaço de endereço virtual da CPU?

Foi útil?

Solução

O IOMMU é muito útil porque fornece um conjunto de registos de mapeamento.Ele pode fazer com que qualquer memória física apareça dentro do intervalo de endereços acessível por um dispositivo e também pode fazer com que buffers fisicamente dispersos pareçam contíguos aos dispositivos.Isso não é bom para placas PCI/PCI-Express de terceiros ou máquinas remotas que tentam acessar o deslocamento físico bruto de uma GPU nVidia, pois isso pode resultar em não na verdade acessar as regiões de memória pretendidas ou inibir/restringir tais acessos por cartão pela unidade IOMMU.Isso deve ser desabilitado, então, porque

"RDMA para GPUDirect atualmente depende de todas as moradas físicas a serem o mesmo do ponto de vista dos dispositivos PCI."

-nVidia, Considerações de design para rDMA e GPUDirect

Quando os drivers tentam utilizar a MMU da CPU e mapear regiões de E/S mapeada de memória (MMIO) para uso no espaço do kernel, eles normalmente mantêm o endereço retornado do mapeamento de memória para si mesmos.Como cada driver opera dentro de seu próprio contexto ou namespace, a troca desses mapeamentos entre os drivers da nVidia e os drivers de outros fornecedores terceirizados que desejam suportar rDMA+GPUDirect seria muito difícil e resultaria em uma solução específica do fornecedor (possivelmente até mesmo produto -específico se os drivers variarem muito entre produtos de terceiros).Além disso, os sistemas operacionais atuais não têm nenhuma boa solução para a troca de mapeamentos MMIO entre drivers, portanto, a nVidia exporta várias funções que permitem que drivers de terceiros acessem facilmente essas informações a partir do próprio espaço do kernel.

A nVidia impõe o uso de “endereçamento físico” para acessar cada placa via rDMA para GPUDirect.Isto simplifica muito o processo de movimentação de dados de um computador para um barramento PCI-Express de um sistema remoto, usando o esquema de endereçamento físico dessa máquina sem ter que se preocupar com problemas relacionados ao endereçamento virtual (por exemplo,resolução de endereços virtuais para físicos).Cada cartão possui um endereço físico no qual reside e pode ser acessado nesse deslocamento;apenas um pequeno pedaço de lógica deve ser adicionado ao driver de terceiros que tenta executar operações rDMA.Além disso, esses registradores de endereço base de 32 ou 64 bits fazem parte do espaço de configuração PCI padrão, portanto, o endereço físico da placa pode ser facilmente obtido simplesmente lendo seus BARs, em vez de ter que obter um endereço mapeado obtido pelo driver da nVidia. ao anexar ao cartão.O Universal Virtual Addressing (UVA) da nVidia cuida dos mapeamentos de endereços físicos mencionados acima para uma região de memória aparentemente contígua para espaço do usuário aplicativos, assim:

CUDA Virtual Address Space

Essas regiões de memória são divididas em três tipos:CPU, GPU e FREE, todos documentados aqui.

Porém, voltando ao seu caso de uso:já que você está em espaço do usuário, você não tem acesso direto ao espaço de endereço físico do sistema e os endereços que está usando provavelmente são endereços virtuais fornecidos pelo UVA da nVidia.Supondo que nenhuma alocação anterior tenha sido feita, sua alocação de memória deve residir no deslocamento +0x00000000, o que resultaria na visualização do mesmo deslocamento da própria GPU.Se você alocasse um segundo buffer, imagino que veria esse buffer iniciar imediatamente após o final do primeiro buffer (no deslocamento +0x00100000 da base endereço virtual da GPU no seu caso de alocações de 1 MB).

Se você estivesse em espaço do kernel, no entanto, e estivesse escrevendo um driver para a placa da sua empresa para utilizar rDMA para GPUDirect, você usaria os endereços físicos de 32 ou 64 bits atribuídos à GPU pelo BIOS e/ou sistema operacional do sistema para dados rDMA diretamente de e para o GPU em si.

Além disso, pode ser interessante notar que nem todos os mecanismos DMA realmente suportam endereços virtuais para transferências - na verdade, a maioria requer endereços físicos, como o tratamento de endereçamento virtual de um mecanismo DMA pode ficar complexo (página 7), portanto, muitos mecanismos DMA não têm suporte para isso.

Para responder à pergunta do título da sua postagem:Atualmente, a nVidia suporta apenas endereçamento físico para rDMA+GPUDirect no espaço do kernel.Para espaço do usuário aplicativos, você sempre usará o endereço virtual da GPU fornecido pelo UVA da nVidia, que está no espaço de endereço virtual da CPU.


Em relação ao seu aplicativo, aqui está um detalhamento simplificado do processo que você pode executar para operações rDMA:

  1. Seu espaço do usuário O aplicativo cria buffers, que estão no escopo do espaço de endereçamento virtual unificado que a nVidia fornece (endereços virtuais).
  2. Faça uma chamada para cuPointerGetAttribute(...) para obter tokens P2P;esses tokens pertencem à memória dentro do contexto do CUDA.
  3. Envie todas essas informações para espaço do kernel de alguma forma (por ex.IOCTL, leitura/gravação em seu driver, etc).No mínimo, você vai querer que essas três coisas acabem em seu espaço do kernel motorista:
    • Token(s) P2P retornado(s) por cuPointerGetAttribute(...)
    • Endereço(s) virtual(es) UVA do(s) buffer(s)
    • Tamanho do(s) buffer(es)
  4. Agora traduza esses endereços virtuais para seus endereços físicos correspondentes chamando as funções de espaço do kernel da nVidia, já que esses endereços são mantidos nas tabelas de páginas da nVidia e podem ser acessados ​​com as funções exportadas da nVidia, como: nvidia_p2p_get_pages(...), nvidia_p2p_put_pages(...), e nvidia_p2p_free_page_table(...).
  5. Use esses endereços físicos adquiridos na etapa anterior para inicializar seu mecanismo DMA que manipulará esses buffers.

Uma explicação mais aprofundada deste processo pode ser encontrada aqui.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top