IOMMU は、マッピング レジスタのセットを提供するという点で非常に便利です。デバイスがアクセスできるアドレス範囲内に物理メモリが表示されるように調整でき、物理的に分散したバッファがデバイスにとって連続して見えるようにすることもできます。これは、nVidia GPU の生の物理オフセットにアクセスしようとするサードパーティの PCI/PCI-Express カードやリモート マシンには適していません。 実は IOMMU ユニットによるメモリの意図された領域へのアクセス、またはカードごとのアクセスの禁止/制限。したがって、これを無効にする必要があります。
「GPUDirect の RDMA は現在依存しています すべての物理アドレスは、PCIデバイスの観点から同じです."
-nVidia、 rDMA と GPUDirect の設計上の考慮事項
ドライバーが CPU の MMU を利用し、カーネル空間内で使用するためにメモリー マップド I/O (MMIO) の領域をマップしようとすると、ドライバーは通常、メモリー マッピングから返されたアドレスをドライバー自身に保持します。各ドライバーは独自のコンテキストまたは名前空間内で動作するため、nVidia のドライバーと、rDMA+GPUDirect のサポートを希望する他のサードパーティ ベンダーのドライバーとの間でこれらのマッピングを交換することは非常に困難であり、ベンダー固有のソリューション (おそらく製品でも) が必要になります。 -ドライバーがサードパーティの製品間で大きく異なる場合に固有)。また、現在のオペレーティング システムにはドライバー間で MMIO マッピングを交換するための適切なソリューションがありません。そのため、nVidia は、サードパーティ ドライバーがカーネル空間自体からこの情報に簡単にアクセスできるようにするいくつかの関数をエクスポートします。
nVidia は、GPUDirect の rDMA 経由で各カードにアクセスするために「物理アドレス指定」の使用を強制します。これにより、仮想アドレス指定に関連する問題 (例:仮想アドレスを物理アドレスに解決します)。各カードには物理アドレスがあり、このオフセットでアクセスできます。rDMA 操作を実行しようとするサードパーティ ドライバーに追加する必要があるロジックはほんの少しだけです。また、これらの 32 ビットまたは 64 ビットのベース アドレス レジスタは標準の PCI 構成空間の一部であるため、カードの物理アドレスは、nVidia のドライバが取得したマップされたアドレスを取得するのではなく、BAR から読み取るだけで簡単に取得できます。カードに貼り付けると。nVidia のユニバーサル仮想アドレス指定 (UVA) は、一見連続しているように見えるメモリ領域への前述の物理アドレス マッピングを処理します。 ユーザースペース アプリケーションは次のようになります。
これらのメモリ領域はさらに 3 つのタイプに分類されます。CPU、GPU、FREE、すべて文書化されています ここ.
ただし、使用例に戻ります。あなたがいるから ユーザースペース, 、システムの物理アドレス空間に直接アクセスすることはできず、使用しているアドレスはおそらく nVidia の UVA によって提供される仮想アドレスです。以前に割り当てが行われていないと仮定すると、メモリ割り当てはオフセット +0x00000000 に存在するはずで、その結果、GPU 自体の同じオフセットが表示されることになります。2 番目のバッファを割り当てる場合、このバッファは最初のバッファの終了直後 (ベースからのオフセット +0x00100000 で開始される) が表示されると思います。 仮想アドレス 1 MB 割り当ての場合の GPU)。
もしあなたが入っていたら カーネルスペース, ただし、GPUDirect に rDMA を利用するために会社のカードのドライバーを作成していた場合、システムの BIOS や OS によって GPU に割り当てられた 32 ビットまたは 64 ビットの物理アドレスを使用して、rDMA データを直接やり取りすることになります。 GPU、それ自体。
さらに、すべての DMA エンジンが転送用の仮想アドレスを実際にサポートしているわけではないことも注目に値します。実際、ほとんどの DMA エンジンは DMA エンジンからの仮想アドレス指定を処理するため、物理アドレスを必要とします。 複雑になる可能性があります (7 ページ)、したがって、多くの DMA エンジンはこれをサポートしていません。
ただし、投稿のタイトルからの質問に答えるには、次のようにします。nVidia は現在、rDMA+GPUDirect の物理アドレス指定のみをサポートしています。 カーネル空間内. 。のために ユーザースペース アプリケーションでは、CPU の仮想アドレス空間にある nVidia の UVA によって与えられる GPU の仮想アドレスを常に使用することになります。
アプリケーションに関連して、rDMA 操作で実行できるプロセスの簡略化された内訳を次に示します。
- あなたの ユーザースペース アプリケーションは、nVidia が提供する統合仮想アドレス空間 (仮想アドレス) の範囲内にあるバッファを作成します。
- に電話をかける
cuPointerGetAttribute(...)
P2Pトークンを取得するため。これらのトークンは、CUDA のコンテキスト内のメモリに関係します。 - このすべての情報を次の宛先に送信してください カーネルスペース どういうわけか(例:IOCTL、ドライバーへの読み取り/書き込みなど)。少なくとも、これら 3 つは最終的に必要になります。 カーネルスペース 運転者:
- によって返された P2P トークン
cuPointerGetAttribute(...)
- バッファの UVA 仮想アドレス
- バッファのサイズ
- によって返された P2P トークン
- 次に、nVidia のカーネル空間関数を呼び出して、これらの仮想アドレスを対応する物理アドレスに変換します。これらのアドレスは nVidia のページ テーブルに保持されており、関数の nVidia のエクスポートでアクセスできるためです。
nvidia_p2p_get_pages(...)
,nvidia_p2p_put_pages(...)
, 、 そしてnvidia_p2p_free_page_table(...)
. - 前の手順で取得したこれらの物理アドレスを使用して、これらのバッファを操作する DMA エンジンを初期化します。
このプロセスのより詳細な説明は、こちらをご覧ください。 ここ.