NVIDIA RDMA GPudirect opera sempre solo indirizzi fisici (nello spazio degli indirizzi fisici della CPU)?

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

Domanda

Come sappiamo: http://en.wikipedia.org/wiki/iommu#advantages

Il paging per la memoria periferica può essere supportato da un Iommu. Una periferica che utilizza l'estensione PRI (ATS) Page Services Services Services Services Services (PRI) può rilevare e segnalare la necessità di Servizi di Gestione memoria.

enter image description here

Ma quando utilizziamo Nvidia GPU con Cuda> = 5.0, possiamo usare RDMA GpUdiRect e saperlo:

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

Tradizionalmente, le risorse come le finestre a barre sono mappate sullo spazio degli indirizzi dell'utente o del kernel utilizzando la MMU della CPU come indirizzi I/O (MMIO) mappati di memoria. Tuttavia, perché Gli attuali sistemi operativi non hanno meccanismi sufficienti per lo scambio di regioni MMIO tra i driver, Le esportazioni del driver del kernel NVIDIA funziona per eseguire le traduzioni e le mappature degli indirizzi necessari.

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

RDMA per gpudirect attualmente si basa su tutti gli indirizzi fisiciessere lo stesso dal punto di vista dei dispositivi PCI. Ciò lo rende incompatibile con iommus e quindi devono essere disabilitati per RDMA affinché gpudirect funzioni.

E se allochiamo e mappiamo la CPU-RAM all'UVA, come qui:

#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;
}

Riceviamo pari puntatori in Windwos7x64, ciò significa che cudaHostGetDevicePointer() fare niente:

host_src_ptr = 68719476736

UVA_SRC_PTR = 68719476736

Cosa significa "meccanismi sufficienti per lo scambio di regioni MMIO tra i driver", ciò che il meccanismo è qui e perché non posso usare Iommu utilizzando l'indirizzo virtuale per accedere tramite PCIe nella regione fisica della barra - un altro dispositivo mappato di memoria tramite PCIe ?

E questo significa che RDMA Gpudirect gestisce sempre solo indirizzi fisici (nello spazio degli indirizzi fisici della CPU), ma perché inviamo alla funzione del kernel uva_src_ptr che è uguale a host_src_ptr - Puntatore semplice nello spazio degli indirizzi virtuali della CPU?

È stato utile?

Soluzione

L'IOMMU è molto utile in quanto fornisce una serie di registri di mappatura. Può organizzare che qualsiasi memoria fisica appaia all'interno dell'intervallo di indirizzi accessibile da un dispositivo e può far sembrare contigui anche i buffer dispersi fisicamente ai dispositivi. Questo non va bene per le schede PCI/PCI-Express di terze parti o macchine remote che tentano di accedere all'offset fisico grezzo di una GPU NVIDIA, in quanto ciò potrebbe comportare non in realtà Accesso alle regioni previste della memoria o inibizione/limitazione di tali accessi su base pronta da parte dell'unità IOMMU. Questo deve essere disabilitato, quindi, perché

"RDMA per gpudirect attualmente si basa Tutti gli indirizzi fisici sono gli stessi dal punto di vista dei dispositivi PCI."

-nvidia, Considerazioni sulla progettazione per RDMA e GpUDirect

Quando i conducenti tentano di utilizzare le regioni MMU e mappa della CPU di I/O mappate di memoria (MMIO) per l'uso all'interno dello spazio del kernel, in genere mantengono l'indirizzo restituito dalla mappatura della memoria a se stessi. Poiché ogni driver opera nel proprio contesto o spazio dei nomi, scambiando queste mappature tra i conducenti di Nvidia e gli altri conducenti di un fornitore di terze parti che desiderano supportare RDMA+Gpudirect sarebbe molto difficile e comporterebbe una soluzione specifica per il fornitore (forse anche il prodotto (anche il prodotto specifico (forse anche il prodotto (anche il prodotto specifico -Specifici se i conducenti variano notevolmente tra i prodotti della terza parte). Inoltre, i sistemi operativi di oggi attualmente non hanno una buona soluzione per lo scambio di mappature MMIO tra i conducenti, quindi NVIDIA esporta diverse funzioni che consentono ai conducenti di terze parti di accedere facilmente a queste informazioni dallo spazio del kernel, stesso.

NVIDIA applica l'uso di "indirizzamento fisico" per accedere a ciascuna carta tramite RDMA per gpudirect. Ciò semplifica notevolmente il processo di spostamento dei dati da un computer al bus PCI-Express di un sistema remoto utilizzando lo schema di indirizzamento fisico di quella macchina senza doversi preoccuparsi dei problemi relativi all'indirizzo virtuale (ad es. Risoluzione degli indirizzi virtuali a quelli fisici). Ogni carta ha un indirizzo fisico a cui risiede e è possibile accedere a questo offset; Solo un po 'di logica deve essere aggiunto al conducente di terze parti che tenta di eseguire operazioni RDMA. Inoltre, questi registri degli indirizzi di base a 32 o 64 bit fanno parte dello spazio di configurazione PCI standard, quindi l'indirizzo fisico della scheda potrebbe essere facilmente ottenuto leggendo semplicemente dalla sua barra piuttosto che dover ottenere un indirizzo mappato che il driver di Nvidia ha ottenuto All'attacco alla carta. L'indirizzamento virtuale universale di Nvidia (UVA) si prende cura delle sopra menzionate le mappature degli indirizzi fisici a una regione di memoria apparentemente contigua spazio utente applicazioni, così:

CUDA Virtual Address Space

Queste regioni di memoria sono ulteriormente divise in tre tipi: CPU, GPU e gratuiti, che sono tutti documentati qui.

Torna al tuo caso di utilizzo, però: dal momento che sei dentro spazio utente, non hai accesso diretto allo spazio degli indirizzi fisici del sistema e gli indirizzi che stai utilizzando sono probabilmente indirizzi virtuali forniti dall'UVA di Nvidia. Supponendo che non siano state fatte allocazioni precedenti, la tua allocazione di memoria dovrebbe risiedere all'offset +0x00000000, il che porterebbe a vedere lo stesso offset della GPU, stessa. Se dovessi allocare un secondo buffer, immagino che vedresti questo buffer iniziare immediatamente dopo la fine del primo buffer (all'offset +0x00100000 dalla base indirizzo virtuale della GPU nel caso di allocazioni di 1 MB).

Se eri dentro Spazio del kernel, tuttavia, e stavi scrivendo un driver per la scheda della tua azienda per utilizzare RDMA per GPudiRect, utilizzeresti gli indirizzi fisici a 32 o 64 bit assegnati alla GPU dal BIOS e/o da OS al sistema RDMA direttamente da e verso il GPU, di per sé.

Inoltre, potrebbe valere la pena notare che non tutti i motori DMA supportano effettivamente gli indirizzi virtuali per i trasferimenti - in effetti, la maggior parte richiede indirizzi fisici, poiché la gestione degli indirizzi virtuali da un motore DMA può diventare complesso (Pagina 7), quindi molti motori DMA non hanno supporto per questo.

Per rispondere alla domanda dal titolo del tuo post, però: Nvidia attualmente supporta solo l'indirizzamento fisico per RDMA+GpUDirect nello spazio del kernel. Per spazio utente Applicazioni, utilizzerai sempre l'indirizzo virtuale della GPU fornita dall'UVA di Nvidia, che si trova nello spazio degli indirizzi virtuali della CPU.


In relazione alla tua applicazione, ecco una rottura semplificata del processo che puoi fare per le operazioni RDMA:

  1. Tuo spazio utente L'applicazione crea buffer, che sono nell'ambito di Space Virtual Indirizzamento unificato che Nvidia fornisce (indirizzi virtuali).
  2. Fare una chiamata a cuPointerGetAttribute(...) per ottenere token P2P; Questi token riguardano la memoria nel contesto di CUDA.
  3. Invia tutte queste informazioni a Spazio del kernel In qualche modo (ad esempio Ioctl, leggi/scrivi al tuo driver, ecc.). Come minimo, vorrai che queste tre cose finiscano nel tuo Spazio del kernel autista:
    • Token p2p restituito da cuPointerGetAttribute(...)
    • Indirizzo virtuali UVA dei buffer (i)
    • Dimensione del buffer (i)
  4. Ora traduci quegli indirizzi virtuali nei loro corrispondenti indirizzi fisici chiamando le funzioni dello spazio del kernel di NVIDIA, poiché questi indirizzi sono tenuti nelle tabelle della pagina di NVIDIA e si può accedere all'esportazione di Nvidia della funzione, come: come: ad esempio: come: ad esempio: come: ad esempio: nvidia_p2p_get_pages(...), nvidia_p2p_put_pages(...), e nvidia_p2p_free_page_table(...).
  5. Utilizzare questi indirizzi fisici acquisiti nel passaggio precedente per inizializzare il motore DMA che manipolerà quei buffer.

È possibile trovare una spiegazione più approfondita di questo processo qui.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top