3

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

我获得了我使用的英特尔卡的 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 
}                        

我究竟做错了什么?

4

1 回答 1

1

cudaHostRegister()在已经分配的主机内存上运行,所以你必须通过addr,而不是&addr.

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

于 2013-10-23T20:25:19.570 回答