nvidia-peermem和dmabuf两种GDR方式的区别

NCCL 的源码中,具有两种方式的 GDR,nvidia-peermem和dmabuf,在注册收发缓冲区时会优先选择后面一种方式。源码注释中的nv_peermem和nvidia-peermem是同一个东西,在不同版本的叫法有所不同。

for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
    resources->buffers[p] = NCCL_NET_MAP_GET_POINTER(map, cpu, buffs[p]);
    if (resources->buffers[p]) {

      /* DMA-BUF support */
      int type = NCCL_NET_MAP_DEV_MEM(map, buffs[p]) ? NCCL_PTR_CUDA : NCCL_PTR_HOST;
      if (type == NCCL_PTR_CUDA && resources->useDmaBuf) {
        int dmabuf_fd;
        CUCHECK(cuMemGetHandleForAddressRange((void *)&dmabuf_fd, (CUdeviceptr)resources->buffers[p], resources->buffSizes[p], CU_MEM_RANGE_HANDLE_TYPE_DMA_BUF_FD, 0));
        NCCLCHECK(proxyState->ncclNet->regMrDmaBuf(resources->netRecvComm, resources->buffers[p], resources->buffSizes[p], type, 0ULL, dmabuf_fd, &resources->mhandles[p]));
        (void)close(dmabuf_fd);
      } else // FALL-THROUGH to nv_peermem GDR path

      {
        NCCLCHECK(proxyState->ncclNet->regMr(resources->netRecvComm, resources->buffers[p], resources->buffSizes[p], NCCL_NET_MAP_DEV_MEM(map, buffs[p]) ? NCCL_PTR_CUDA : NCCL_PTR_HOST, &resources->mhandles[p]));
      }
    }
  }

中文网站上,有关 dmabuf 和ibv_reg_dmabuf_mr的相关资料比较少。在阅读源码时,笔者不确定这两种方式是否有性能上的差异,因此在 NCCL 的仓库下提出了一个issue (https://github.com/NVIDIA/nccl/issues/908),得到的回复是,这两者之间没有性能上的差别。

之后,笔者调研了一下相关资料,对比了两者之间的差异,在此作为二手资料进行分享。

虽然 RDMA 这个概念已经很早了,但是 GDR 的提出不过是最近十年左右的事情——早期并没有大量数据直接传输到 GPU 上的需求。因此,GDR 这一方案也并没有一个明确的标准。GDR 与普通 RDMA 的区别在于,计算机访问显存和内存的方式不一样,早期的 libverbs 接口中,并不存在ibv_reg_dmabuf_mr,只存在ibv_reg_mr这一通用的接口。因此cudaMalloc分配出的假显存被注册时,IB core 是不知道这是一片映射得到的内存,在尝试去 pin 这块内存时,内核会报错,具体的原因可以参见pin_user_pages这一函数的设计文档,里面有比较详细的介绍。

nvidia-peermem的这一方案,是 Mallenox 公司推出的。它没有改变 libverbs 的接口,而是修改了自身的驱动,对于不能 pin 住的内存,它会轮询额外加载的peer_memory_client模块,让这些模块尝试翻译并 pin 住这些内存区域。对于 N 卡来说,这一模块就是nvidia-peermem。在忽略 GPU 页表切换时,其实这一模块就是完成了一个地址翻译的工作,数据传输本质上还是依赖于显卡驱动的。

ibv_reg_dmabuf_mr是 OpenFabric 提出的方案,为了反对 Mallenox 公司对 GDR 方案的垄断:nvidia-peermem需要绑定 Mallenox 的网卡。这一方案利用 Kernel 中设计的 dmabuf,将其作为中间值,从而让 RNIC 能够拿到翻译后的物理地址。ibv_reg_dmabuf_mr就是为了这一方案而新引入 libverbs 中的一个接口。这一方案的实现是更加优雅的,并且在注册 mr 时不需要轮询,在注册时的性能“理论上”会好一些。ibv_reg_dmabuf_mr这一接口的具体实现,直至 Linux Kernel 5.12 才被加入内核中,因此对软件栈的要求是比较高的。

如果使用的是 Mallenox 网卡,两种方案并没有本质上的区别,因为数据传输都是由显卡驱动完成的。

文章来源:https://tangrc99.com/2023/07/05/nvidia-peermem%20%E5%92%8C%20dmabuf%20%E4%B8%A4%E7%A7%8D%20GDR%20%E6%96%B9%E5%BC%8F%E7%9A%84%E5%8C%BA%E5%88%AB/

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://sulao.cn/post/1075

评论列表

0%