2013-10-22 3 views
3

Linux의 다른 PCIe 장치에서 직접 NIC의 DMA 주소에 액세스하려고합니다. 특히, CPU를 모두 우회하기 위해 NVIDIA GPU에서 읽으려고합니다. 나는 zero-copy 네트워킹과 DMA를 사용자 공간 게시물에 대해 연구했지만, 질문에 답하지 않았거나 커널 공간에서 사용자 공간으로의 복사를 포함하지 않았습니다. 지연과의 불일치로 인해 CPU 클럭을 사용하지 않으려 고하고 있으며 대기 시간 요구가 매우 큽니다.다른 장치에 대한 PCIe를 통한 DMA

내가 사용하는 인텔 카드 용 NIC 드라이버 (e1000e 드라이버)를 보유하고 있으며 링 버퍼가 할당 된 곳을 찾았습니다. 내가 읽었던 이전 논문에서 알 수 있듯이, 나는 dma_addr_t 유형의 디스크립터에 관심이있다. 또한 dma라는 rx_ring 구조체의 멤버가 있습니다. desc와 dma 멤버 모두를 ioctl 호출을 사용하여 전달하지만 GPU에서 0 이외에 아무것도 얻을 수 없습니다. 내가 잘못 뭐하는 거지

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 
}       

다음과 같이

GPU의 코드는?

+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을 사용했습니다. 나는 아직도 단지 0을 얻는다. 입력하지 않으면 void로 캐스트합니다. void가 u64 (unsigned long long)와 호환되지 않는다는 오류가 발생합니다. – jrk0414

+0

'cudaHostRegister()'에 전달할 주소가 유효한 호스트 메모리 주소인지 확인하십시오. 또한, 네, 직접'u64'를'void *'로 캐스팅 할 수 없습니다. 중간에'uintptr_t '를 사용해야합니다. 'u * u = (u64) (uintptr) t) p;''void * p = (void *) (uintptr_t) u;' – ArchaeaSoftware