テクニカル ドキュメント #142



Doc ID: 142
製品: WinDriver
Version:  14.40

WinDriver を使用して GPUDirect で PCI デバイスと NVIDIA GPU 間の DMA 転送を実装

GPUDirect RDMA とは

GPUDirect RDMA は、GPU と PCI Express デバイス間でダイレクト・メモリ・アクセス (DMA) を実行することを可能にする、一部の NVIDIA GPU で利用可能な機能です。お使いの GPU がこの目的で GPUDirect をサポートしていることを、NVIDIA のウェブサイトで確認してください。

注意:
NVIDIA GPUDirect RDMA は現在 Linux のみでサポートされています。将来的には、さらに多くの GPU や OS のサポートを追加予定です。

システム要件

  1. GPUDirect をサポートする NVIDIA GPU
  2. WinDriver と通信する PCIe デバイス

ソフトウェアの前提条件

  1. お使いの GPU 用の NVIDIA カーネル ドライバがインストールされている
  2. GPUDirect をサポートする CUDA バージョン (バージョン 10 でテスト済み) と NVCC コンパイラーがインストールされている

WinDriver のインストール

WinDriver を tar ファイルから解凍します。

cd WinDriver/redist

WinDriver のカーネルモジュールが NVIDIA のカーネルモジュールとリンクされていることを確認して、GPUDIRECT を許可してください。

./configure –with-gpudirect-source=<<YOUR_NVIDIA_KERNEL_SOURCE_DIRECTORY>>/kernel
sudo make && sudo make install

DMA を CPU から GPU に移動

GPUDirect DMA ルーチンの実装に移る前に、デバイスとコンピュータ RAM 間の「通常の」DMA ルーチンを実装し、テストしておくことを強くお勧めします。

WinDriver ベースのコードに DMA ルーチンを既に実装している場合、メインメモリの代わりに GPU メモリに DMA を実行するには、以下の手順を実行してください。

コンパイルを修正

make を使ってコンパイルする場合は、こちらの指示に従ってください。
CMake を使用する場合は、以下の詳細な例を参照してください。

  1. gcc の代わりに CUDA コンパイラ (nvcc) でアプリをコンパイルするように makefile を変更します。
  2. makefile を変更して ld の代わりに CUDA コンパイラ (nvcc) でアプリをリンクするようにします。
  3. リンカフラグ(LFLAGS)に -lcuda を追加して、CUDA 共有ライブラリとリンクするようにします。
  4. リンカフラグから -fno-pie と -m$(USER_BITS) を削除します。

コードを修正

  1. 下記を追加
  2. #include <cuda.h>
    #include <cuda_runtime.h>
  3. 関数 WDC_DMASGBufLock() の pBuf パラメータのメモリを割り当てるため、通常の malloc() を使用する代わりに、cudaMalloc() を使用してください。
  4. WDC_DMASGBufLock() の dwOptions パラメータに DMA_GPUDIRECT フラグが含まれていることを確認します。
  5. 次のコードを追加して、DMA バッファ (この例では pDma->pBuf) との同期メモリ操作を有効にします。
  6. int flag = 1;
    if (CUDA_SUCCESS != cuPointerSetAttribute(&flag,
    CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, (CUdeviceptr)pDma->pBuf))
    {
    printf("cuDeviceGet failed\n");
    return;
    }

  7. GPU メモリにアクセスするために CUDA 関数を使用してください: cudaMemcpy, cudaFree など。GPU メモリへのポインタで通常のメモリ管理関数を使用すると、クラッシュにつながる可能性があります。

注意:
通常のメモリバッファ (cudaMalloc() を使用して割り当てられていない) で割り当てられたバッファで DMA_GPUDIRECT フラグを使用して WDC_DMASGBufLock() を呼び出すと、内部システムエラー (ステータス 0x20000007) が発生します。

CMakeの例

CMake を使用してコードをコンパイルする場合、次の手順を参考として使用してください。

cmake_minimum_required(VERSION 3.0)

set(WD_BASEDIR ~/WinDriver) #change according to your installation path

project(my_wd_gpudirect_project C)
include(${WD_BASEDIR}/include/wd.cmake)
include_directories(
${WD_BASEDIR}
${WD_BASEDIR}/include
)

set(SRCS my_wd_gpudirect_project.c)

add_executable(my_wd_gpudirect_project ${SRCS} ${SAMPLE_SHARED_SRCS})

#link with and libwdapiXXXX and libcuda
target_link_libraries(my_wd_gpudirect_project wdapi${WD_VERSION} cuda)
set_target_properties(my_wd_gpudirect_project PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${ARCH}/"
)

#remove definitions to allow compilation with nvcc
remove_definitions("-Wno-unused-result -Wno-write-strings ")
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")

#change compiler to nvcc
set(CMAKE_C_COMPILER /usr/local/cuda-10.2/bin/nvcc)

#add GPUDIRECT definition to compilation
target_compile_definitions(my_wd_gpudirect_project PRIVATE GPUDIRECT)