2013-10-22 47 views
3

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

我拿到了我使用的intel卡(e1000e驱动程序)的NIC驱动程序,并且我找到了环形缓冲区的分配位置。正如我从之前的一篇文章中所理解的那样,我会对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 
}       

我在做什么错?

+0

评论中它说“FPGA”,它应该说“NIC缓冲区”? –

+0

是的,它应该。我从另一个例子中复制了部分代码,在Windows中做了非常类似的事情。他们从FPGA PCI-e板读取数据。对于那个很抱歉。 – jrk0414

+0

您有没有机会看NVIDIA的GPUDirect文档:http://docs.nvidia.com/cuda/gpudirect-rdma/index.html – njuffa

回答

1

cudaHostRegister()在已分配的主机内存上运行,所以您必须通过addr而不是&addr。如果addr不是主机指针,这将不起作用。如果它一个主机指针,你的功能接口应该使用void *然后就不需要该类型转换。

+0

使用你的建议,我用(void *)addr代替(void **)&addr。尽管我仍然只有零。如果我没有将它转换为void *,我会得到一个错误,指出void与u64(这是一个无符号long long)不兼容。 – jrk0414

+0

确保您传递给'cudaHostRegister()'的地址是有效的主机内存地址。另外,是的,你不能直接将'u64'转换为'void *',你必须在中间粘贴一个中间转换为'uintptr_t'。 'u64 u =(u64)(uintptr)t)p;''void * p =(void *)(uintptr_t)u;'' – ArchaeaSoftware