【问题标题】:DMA over PCIe to other deviceDMA over PCIe 到其他设备
【发布时间】:2013-10-31 20:16:13
【问题描述】:

我正在尝试直接从 Linux 中的另一个 PCIe 设备访问 NIC 中的 DMA 地址。具体来说,我正在尝试从 NVIDIA GPU 读取它以绕过 CPU。我研究了零拷贝网络和 DMA 到用户空间的帖子,但他们要么没有回答问题,要么涉及从内核空间到用户空间的一些拷贝。由于延迟不一致,我试图避免使用任何 CPU 时钟,并且我有非常严格的延迟要求。

我获得了我使用的 intel 卡的 NIC 驱动程序(e1000e 驱动程序),我找到了分配环形缓冲区的位置。正如我从之前阅读的一篇论文中了解到的那样,我会对 dma_addr_t 类型的描述符感兴趣。它们还有一个名为 dma 的 rx_ring 结构成员。我使用 ioctl 调用同时传递了 desc 和 dma 成员,但除了零之外,我无法在 GPU 中获得任何东西。

GPU代码如下:

int *setup_gpu_dma(u64 addr)                                                     
{                                                                                
    // Allocate GPU memory                                                       
    int *gpu_ptr;                                                                
    cudaMalloc((void **) &gpu_ptr, MEM_SIZE);                                    

    // Allocate memory in user space to read the stuff back                      
    int *h_data;                                                                 
    cudaMallocHost((void **)&h_data, MEM_SIZE);                                  

    // Present FPGA memory to CUDA as CPU locked pages                           
    int error = cudaHostRegister((void **) &addr, MEM_SIZE,                      
        CU_MEMHOSTALLOC_DEVICEMAP);                                              
    cout << "Allocation error = " << error << endl;                              

    // DMA from GPU memory to FPGA memory                                        
    cudaMemcpy((void **) &gpu_ptr, (void **)&addr,   MEM_SIZE, cudaMemcpyHostToDevice);
    cudaMemcpy((void **) &h_data, (void **)&gpu_ptr, MEM_SIZE, cudaMemcpyDeviceToHost);

    // Print the data                                                            

    // Clean up 
}                        

我做错了什么?

【问题讨论】:

  • 在 cmets 中说“FPGA”的地方,应该说“NIC 缓冲区”吗?
  • 是的,应该。我从另一个例子中复制了这段代码的一部分,在 Windows 中做了非常相似的事情。他们正在从 FPGA PCI-e 板上读取数据。对此感到抱歉。
  • 您有没有机会查看 NVIDIA 的 GPUDirect 文档:docs.nvidia.com/cuda/gpudirect-rdma/index.html
  • 是的,我有,但是有几个问题。首先,这不适用于 Geforce GPU。与其将 GPU 地址提供给 NIC,不如将 NIC 地址提供给 GPU。其次,NIC 驱动程序使用环形缓冲区,据我了解,这使得它很难与 GPU 内存一起使用。

标签: linux cuda dma nic pci-e


【解决方案1】:

cudaHostRegister() 在已分配的主机内存上运行,因此您必须传递 addr,而不是 &amp;addr

如果addr 不是主机指针,这将不起作用。如果它一个主机指针,你的函数接口应该使用void *,那么就不需要类型转换了。

【讨论】:

  • 根据您的建议,我使用 (void*) addr 而不是 (void *)&addr。我仍然只得到零。如果我不键入将其强制转换为 void,我会收到一条错误消息,指出 void 与 u64 不兼容(这是一个无符号长整数)。
  • 确保您传递给cudaHostRegister() 的地址是有效的主机内存地址。另外,是的,您不能直接将u64 转换为void *,您必须在两者之间将中间转换为uintptr_tu64 u = (u64) (uintptr) t) p;void *p = (void *) (uintptr_t) u;
猜你喜欢
  • 2019-11-19
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多