GPUDirect RDMA 和 GPUDirect Storage#

关于 GPUDirect RDMA 和 GPUDirect Storage#

GPUDirect RDMA 是 NVIDIA GPU 中的一项技术,它允许 GPU 和第三方对等设备之间使用 PCI Express 进行直接数据交换。第三方设备可以是网络接口,例如 NVIDIA ConnectX SmartNIC 或 BlueField DPU,或视频采集适配器。

GPUDirect Storage (GDS) 实现了本地或远程存储(例如 NFS 服务器或 NVMe/NVMe over Fabric (NVMe-oF))与 GPU 内存之间的直接数据路径。GDS 在 GPU 内存和存储之间执行直接内存访问 (DMA) 传输。DMA 避免了通过 CPU 的反弹缓冲区。此直接路径提高了系统带宽,并降低了 CPU 的延迟和利用率负载。

为了支持 GPUDirect RDMA,需要用户空间 CUDA API。内核模式支持由以下两种方法之一提供:来自 Linux 内核的 DMA-BUF 或旧版 nvidia-peermem 内核模块。NVIDIA 建议使用 DMA-BUF,而不是使用 GPU 驱动程序中的 nvidia-peermem 内核模块。

从 Operator 的 v23.9.1 版本开始,Operator 使用 GDS 驱动程序版本 2.17.5 或更高版本。此版本及更高版本仅在使用 NVIDIA Open GPU 内核模块驱动程序时才受支持。用于安装 Operator 的示例命令包括 Helm 的 --set useOpenKernelModules=true 命令行参数。

与 Network Operator 结合使用,GPU Operator 可用于设置网络相关组件,例如网络设备内核驱动程序和 Kubernetes 设备插件,以使工作负载能够利用 GPUDirect RDMA 和 GPUDirect Storage。有关安装信息,请参阅 Network Operator 文档

常用先决条件#

配置 GPUDirect RDMA 或 GPUDirect Storage 的先决条件取决于您是使用来自 Linux 内核的 DMA-BUF 还是旧版 nvidia-peermem 内核模块。

技术

DMA-BUF

旧版 NVIDIA-peermem

GPU 驱动程序

需要 Open Kernel 模块驱动程序。

任何受支持的驱动程序。

CUDA

CUDA 11.7 或更高版本。CUDA 运行时由驱动程序提供。

无最低版本。CUDA 运行时由驱动程序提供。

GPU

图灵架构数据中心、Quadro RTX 和 RTX GPU 或更高版本。

所有数据中心、Quadro RTX 和 RTX GPU 或更高版本。

网络设备驱动程序

MLNX_OFED 或 DOCA-OFED 是可选的。您可以使用来自软件包管理器的 Linux 驱动程序软件包。

需要 MLNX_OFED 或 DOCA-OFED。

Linux 内核

5.12 或更高版本。

无最低版本。

  • 确保安装了网络设备驱动程序。

    您可以使用 Network Operator 来管理 MLNX_OFED 和 DOCA-OFED 驱动程序的驱动程序生命周期。

    您可以在每台主机上安装驱动程序。有关 MLNX_OFED、DOCA-OFED 和 Linux 内置驱动程序的信息,请参阅网络文档中的 Adapter Software

  • 对于 VMware vSphere 上的安装,请参阅以下其他先决条件

    • 确保网络接口控制器和 NVIDIA GPU 位于同一 PCIe IO 根复合体中。

    • 启用以下 PCI 选项

      • pciPassthru.allowP2P = true

      • pciPassthru.RelaxACSforP2P = true

      • pciPassthru.use64bitMMIO = true

      • pciPassthru.64bitMMIOSizeGB = 128

      有关配置设置的信息,请参阅 VMWare 的 在 vSphere 7 上部署 AI 就绪的企业平台 文档。

配置 GPUDirect RDMA#

平台支持#

以下平台支持使用 RDMA 的 GPUDirect

  • 裸机和 vSphere VM 上使用 GPU 直通和 vGPU 的 Kubernetes。

  • VMware vSphere with Tanzu。

  • 对于裸机和 vSphere VM 上使用 GPU 直通和 vGPU 配置的 Red Hat OpenShift Container Platform,请参阅 NVIDIA AI Enterprise with OpenShift

有关受支持版本的信息,请参阅平台支持页面上的 GPUDirect RDMA 支持

安装 GPU Operator 并启用 GPUDirect RDMA#

要使用由 Network Operator 安装的 DMA-BUF 和网络设备驱动程序

$ helm install --wait --generate-name \
     -n gpu-operator --create-namespace \
     nvidia/gpu-operator \
     --version=v24.9.2 \
     --set driver.useOpenKernelModules=true

要使用主机上安装的 DMA-BUF 和网络设备驱动程序

$ helm install --wait --generate-name \
     -n gpu-operator --create-namespace \
     nvidia/gpu-operator \
     --version=v24.9.2 \
     --set driver.useOpenKernelModules=true \
     --set driver.rdma.useHostMofed=true

要使用旧版 nvidia-peermem 内核模块而不是 DMA-BUF,请将 --set driver.rdma.enabled=true 添加到上述任一命令。对于使用旧版内核驱动程序,driver.useOpenKernelModules=true 参数是可选的。

验证 GPUDirect with RDMA 的安装#

在安装过程中,NVIDIA 驱动程序守护程序集运行一个 init 容器,以等待网络设备内核驱动程序准备就绪。此 init 容器检查节点上的 Mellanox NIC,并确保必要的内核符号由内核驱动程序导出。

如果您在安装 Operator 时需要使用 driver.rdma.enabled=true 参数,则在验证后,nvidia-peermem-ctr 容器将在每个驱动程序 pod 内启动。

  1. 确认驱动程序守护程序集的 pod 模板包含 mofed-validation init 容器和 nvidia-driver-ctr 容器

    $ kubectl describe ds -n gpu-operator nvidia-driver-daemonset
    

    示例输出

    以下部分输出省略了所有安装通用的 init 容器和容器。

    ...
     Init Containers:
      mofed-validation:
      Container ID:  containerd://5a36c66b43f676df616e25ba7ae0c81aeaa517308f28ec44e474b2f699218de3
      Image:         nvcr.io/nvidia/cloud-native/gpu-operator-validator:v1.8.1
      Image ID:      nvcr.io/nvidia/cloud-native/gpu-operator-validator@sha256:7a70e95fd19c3425cd4394f4b47bbf2119a70bd22d67d72e485b4d730853262c
    ...
     Containers:
      nvidia-driver-ctr:
      Container ID:  containerd://199a760946c55c3d7254fa0ebe6a6557dd231179057d4909e26c0e6aec49ab0f
      Image:         nvcr.io/nvaie/vgpu-guest-driver:470.63.01-ubuntu20.04
      Image ID:      nvcr.io/nvaie/vgpu-guest-driver@sha256:a1b7d2c8e1bad9bb72d257ddfc5cec341e790901e7574ba2c32acaddaaa94625
    ...
      nvidia-peermem-ctr:
      Container ID:  containerd://0742d86f6017bf0c304b549ebd8caad58084a4185a1225b2c9a7f5c4a171054d
      Image:         nvcr.io/nvaie/vgpu-guest-driver:470.63.01-ubuntu20.04
      Image ID:      nvcr.io/nvaie/vgpu-guest-driver@sha256:a1b7d2c8e1bad9bb72d257ddfc5cec341e790901e7574ba2c32acaddaaa94625
    ...
    

    仅当您在安装 Operator 时需要指定 driver.rdma.enabled=true 参数时,nvidia-peermem-ctr 容器才存在。

  2. 仅限旧版:确认 nvidia-peermem-ctr 容器已成功加载 nvidia-peermem 内核模块

    $ kubectl logs -n gpu-operator ds/nvidia-driver-daemonset -c nvidia-peermem-ctr
    

    或者,对于守护程序集中的每个 pod,运行 kubectl logs -n gpu-operator nvidia-driver-daemonset-xxxxx -c nvidia-peermem-ctr

    示例输出

    waiting for mellanox ofed and nvidia drivers to be installed
    waiting for mellanox ofed and nvidia drivers to be installed
    successfully loaded nvidia-peermem module
    

通过执行数据传输来验证安装#

您可以执行以下步骤来验证 GPUDirect with RDMA 是否已正确配置,以及 pod 是否可以执行 RDMA 数据传输。

  1. 获取主机上 InfiniBand 设备的网络接口名称

    $ kubectl exec -it -n network-operator mofed-ubuntu22.04-ds-xxxxx -- ibdev2netdev
    

    示例输出

    mlx5_0 port 1 ==> ens64np1 (Up)
    
  2. 使用 macvlan 网络附件在设备上配置辅助网络

    • 创建一个文件,例如 demo-macvlannetwork.yaml,其内容如下例所示

      apiVersion: mellanox.com/v1alpha1
      kind: MacvlanNetwork
      metadata:
        name: demo-macvlannetwork
      spec:
        networkNamespace: "default"
      master: "ens64np1"
      mode: "bridge"
      mtu: 1500
      ipam: |
        {
          "type": "whereabouts",
          "range": "192.168.2.225/28",
          "exclude": [
            "192.168.2.229/30",
            "192.168.2.236/32"
          ]
        }
      

      ens64np1 替换为上一步中 ibdev2netdev 命令报告的网络接口名称。

    • 应用清单

      $ kubectl apply -f demo-macvlannetwork.yaml
      
    • 确认附加网络已准备就绪

      $ kubectl get macvlannetworks demo-macvlannetwork
      

      示例输出

      NAME                  STATUS   AGE
      demo-macvlannetwork   ready    2023-03-10T18:22:28Z
      
  3. 在集群中两个不同的节点上启动两个运行 mellanox/cuda-perftest 容器的 pod。

    • 创建一个文件,例如 demo-pod-1.yaml,用于第一个 pod,其内容如下所示

      apiVersion: v1
      kind: Pod
      metadata:
        name: demo-pod-1
        annotations:
          k8s.v1.cni.cncf.io/networks: demo-macvlannetwork
          # If a network with static IPAM is used replace network annotation with the below.
          # k8s.v1.cni.cncf.io/networks: '[
          #   { "name": "rdma-net",
          #     "ips": ["192.168.111.101/24"],
          #     "gateway": ["192.168.111.1"]
          #   }
          # ]'
      spec:
        nodeSelector:
          # Note: Replace hostname or remove selector altogether
          kubernetes.io/hostname: nvnode1
        restartPolicy: OnFailure
        containers:
        - image: mellanox/cuda-perftest
          name: rdma-gpu-test-ctr
          securityContext:
            capabilities:
              add: [ "IPC_LOCK" ]
          resources:
            limits:
              nvidia.com/gpu: 1
              rdma/rdma_shared_device_a: 1
            requests:
              nvidia.com/gpu: 1
              rdma/rdma_shared_device_a: 1
      
    • 应用清单

      $ kubectl apply -f demo-pod-1.yaml
      
    • 创建一个文件,例如 demo-pod-2.yaml,用于第二个 pod,其内容如下所示

      apiVersion: v1
      kind: Pod
      metadata:
        name: demo-pod-2
        annotations:
          k8s.v1.cni.cncf.io/networks: demo-macvlannetwork
          # If a network with static IPAM is used replace network annotation with the below.
          # k8s.v1.cni.cncf.io/networks: '[
          #   { "name": "rdma-net",
          #     "ips": ["192.168.111.101/24"],
          #     "gateway": ["192.168.111.1"]
          #   }
          # ]'
      spec:
        nodeSelector:
          # Note: Replace hostname or remove selector altogether
          kubernetes.io/hostname: nvnode2
        restartPolicy: OnFailure
        containers:
        - image: mellanox/cuda-perftest
          name: rdma-gpu-test-ctr
          securityContext:
            capabilities:
              add: [ "IPC_LOCK" ]
          resources:
            limits:
              nvidia.com/gpu: 1
              rdma/rdma_shared_device_a: 1
            requests:
              nvidia.com/gpu: 1
              rdma/rdma_shared_device_a: 1
      
    • 应用清单

      $ kubectl apply -f demo-pod-2.yaml
      
  4. 获取 pod 的 IP 地址

    $ kubectl get pods -o wide
    

    示例输出

    NAME         READY   STATUS    RESTARTS   AGE    IP              NODE      NOMINATED NODE   READINESS GATES
    demo-pod-1   1/1     Running   0          3d4h   192.168.38.90   nvnode1   <none>           <none>
    demo-pod-2   1/1     Running   0          3d4h   192.168.47.89   nvnode2   <none>           <none>
    
  5. 从一个终端,在第一个 pod 上的容器中打开一个 shell 并启动性能测试服务器

    $ kubectl exec -it demo-pod-1 -- ib_write_bw --use_cuda=0 --use_cuda_dmabuf \
        -d mlx5_0 -a -F --report_gbits -q 1
    

    示例输出

    ************************************
    * Waiting for client to connect... *
    ************************************
    
  6. 从另一个终端,在第二个 pod 上的容器中打开一个 shell 并运行性能客户端

    $ kubectl exec -it demo-pod-2 -- ib_write_bw -n 5000 --use_cuda=0 --use_cuda_dmabuf \
        -d mlx5_0 -a -F --report_gbits -q 1 192.168.38.90
    

    示例输出

     ---------------------------------------------------------------------------------------
                        RDMA_Write BW Test
     Dual-port       : OFF          Device         : mlx5_0
     Number of qps   : 1            Transport type : IB
     Connection type : RC           Using SRQ      : OFF
     PCIe relax order: ON
     ibv_wr* API     : ON
     TX depth        : 128
     CQ Moderation   : 100
     Mtu             : 1024[B]
     Link type       : Ethernet
     GID index       : 5
     Max inline data : 0[B]
     rdma_cm QPs     : OFF
     Data ex. method : Ethernet
    ---------------------------------------------------------------------------------------
     local address: LID 0000 QPN 0x01ac PSN 0xc76db1 RKey 0x23beb2 VAddr 0x007f26a2c8b000
     GID: 00:00:00:00:00:00:00:00:00:00:255:255:192:168:02:226
     remote address: LID 0000 QPN 0x01a9 PSN 0x2f722 RKey 0x23beaf VAddr 0x007f820b24f000
     GID: 00:00:00:00:00:00:00:00:00:00:255:255:192:168:02:225
    ---------------------------------------------------------------------------------------
     #bytes     #iterations    BW peak[Gb/sec]    BW average[Gb/sec]   MsgRate[Mpps]
     2          5000             0.11               0.11               6.897101
     4          5000             0.22               0.22               6.995646
     8          5000             0.45               0.45               7.014752
     16         5000             0.90               0.90               7.017509
     32         5000             1.80               1.80               7.020162
     64         5000             3.59               3.59               7.007110
     128        5000             7.19               7.18               7.009540
     256        5000             15.06              14.98              7.313517
     512        5000             30.04              29.73              7.259329
     1024       5000             59.65              58.81              7.178529
     2048       5000             91.53              91.47              5.582931
     4096       5000             92.13              92.06              2.809574
     8192       5000             92.35              92.31              1.408535
     16384      5000             92.46              92.46              0.705381
     32768      5000             92.36              92.35              0.352302
     65536      5000             92.39              92.38              0.176196
     131072     5000             92.42              92.41              0.088131
     262144     5000             92.45              92.44              0.044080
     524288     5000             92.42              92.42              0.022034
     1048576    5000             92.40              92.40              0.011015
     2097152    5000             92.40              92.39              0.005507
     4194304    5000             92.40              92.39              0.002753
     8388608    5000             92.39              92.39              0.001377
    ---------------------------------------------------------------------------------------
    

    命令输出表明数据传输速率约为 92 Gbps。

  7. 删除 pod

    $ kubectl delete -f demo-pod-1.yaml -f demo-pod-2.yaml
    
  8. 删除辅助网络

    $ kubectl delete -f demo-macvlannetworks.yaml
    

使用 GPUDirect Storage#

平台支持#

请参阅平台支持页面上的 GPUDirect Storage 支持

安装 GPU Operator 并启用 GPUDirect Storage#

以下部分适用于以下配置,并描述如何使用 Helm Chart 部署 GPU Operator

  • 裸机和 vSphere VM 上使用 GPU 直通和 vGPU 的 Kubernetes。

从 v22.9.1 开始,GPU Operator 提供了一个选项,可以在 NVIDIA 驱动程序守护程序集的引导期间加载 nvidia-fs 内核模块。从 v23.9.1 开始,GPU Operator 部署了一个 GDS 版本,该版本需要使用 NVIDIA Open Kernel 模块驱动程序。

以下示例命令适用于使用 Network Operator 安装网络设备内核驱动程序的集群。

$ helm install --wait --generate-name \
     -n gpu-operator --create-namespace \
     nvidia/gpu-operator \
     --version=v24.9.2 \
     --set driver.useOpenKernelModules=true \
     --set gds.enabled=true

--set driver.rdma.enabled=true 添加到命令以使用旧版 nvidia-peermem 内核模块。

验证#

在安装过程中,init 容器与驱动程序守护程序集一起使用,以等待网络设备内核驱动程序准备就绪。此 init 容器检查节点上的 Mellanox NIC,并确保必要的内核符号由内核驱动程序导出。验证完成后,nvidia-fs-ctr 容器在驱动程序 pod 内启动。

如果您在安装 Operator 时需要使用 driver.rdma.enabled=true 参数,则在验证后,nvidia-peermem-ctr 容器将在每个驱动程序 pod 内启动。

$ kubectl get pod -n gpu-operator

示例输出

gpu-operator   gpu-feature-discovery-pktzg                                       1/1     Running     0          11m
gpu-operator   gpu-operator-1672257888-node-feature-discovery-master-7ccb7txmc   1/1     Running     0          12m
gpu-operator   gpu-operator-1672257888-node-feature-discovery-worker-bqhrl       1/1     Running     0          11m
gpu-operator   gpu-operator-6f64c86bc-zjqdh                                      1/1     Running     0          12m
gpu-operator   nvidia-container-toolkit-daemonset-rgwqg                          1/1     Running     0          11m
gpu-operator   nvidia-cuda-validator-8whvt                                       0/1     Completed   0          8m50s
gpu-operator   nvidia-dcgm-exporter-pt9q9                                        1/1     Running     0          11m
gpu-operator   nvidia-device-plugin-daemonset-472fc                              1/1     Running     0          11m
gpu-operator   nvidia-device-plugin-validator-29nhc                              0/1     Completed   0          8m34s
gpu-operator   nvidia-driver-daemonset-j9vw6                                     3/3     Running     0          12m
gpu-operator   nvidia-mig-manager-mtjcw                                          1/1     Running     0          7m35s
gpu-operator   nvidia-operator-validator-b8nz2                                   1/1     Running     0          11m
$ kubectl describe pod -n gpu-operator nvidia-driver-daemonset-xxxx
<snip>
 Init Containers:
  mofed-validation:
   Container ID:  containerd://a31a8c16ce7596073fef7cb106da94c452fdff111879e7fc3ec58b9cef83856a
   Image:         nvcr.io/nvidia/cloud-native/gpu-operator-validator:v22.9.1
   Image ID:      nvcr.io/nvidia/cloud-native/gpu-operator-validator@sha256:18c9ea88ae06d479e6657b8a4126a8ee3f4300a40c16ddc29fb7ab3763d46005

 <snip>
 Containers:
  nvidia-driver-ctr:
   Container ID:  containerd://7cf162e4ee4af865c0be2023d61fbbf68c828d396207e7eab2506f9c2a5238a4
   Image:         nvcr.io/nvidia/driver:525.60.13-ubuntu20.04
   Image ID:      nvcr.io/nvidia/driver@sha256:0ee0c585fa720f177734b3295a073f402d75986c1fe018ae68bd73fe9c21b8d8


  <snip>
  nvidia-peermem-ctr:
   Container ID:  containerd://5c71c9f8ccb719728a0503500abecfb5423e8088f474d686ee34b5fe3746c28e
   Image:         nvcr.io/nvidia/driver:525.60.13-ubuntu20.04
   Image ID:      nvcr.io/nvidia/driver@sha256:0ee0c585fa720f177734b3295a073f402d75986c1fe018ae68bd73fe9c21b8d8

  <snip>
  nvidia-fs-ctr:
   Container ID:  containerd://f5c597d59e1cf8747aa20b8c229a6f6edd3ed588b9d24860209ba0cc009c0850
   Image:         nvcr.io/nvidia/cloud-native/nvidia-fs:2.14.13-ubuntu20.04
   Image ID:      nvcr.io/nvidia/cloud-native/nvidia-fs@sha256:109485365f68caeaee1edee0f3f4d722fe5b5d7071811fc81c630c8a840b847b

 <snip>

最后,验证 NVIDIA 内核模块是否已加载到工作节点上

$ lsmod | grep nvidia

nvidia_fs             245760  0
nvidia_peermem         16384  0
nvidia_modeset       1159168  0
nvidia_uvm           1048576  0
nvidia              39059456  115 nvidia_uvm,nvidia_modeset
ib_core               319488  9 rdma_cm,ib_ipoib,iw_cm,ib_umad,rdma_ucm,ib_uverbs,mlx5_ib,ib_cm
drm                   491520  6 drm_kms_helper,drm_vram_helper,nvidia,mgag200,ttm