2011-05-23 38 views
1

我正在開發一個通用流式CUDA內核執行框架,允許在GPU上執行並行數據複製&。是否存在某種與Boost :: thread()和Nvidia CUDA的不兼容?

目前我正在調用C++靜態函數封裝內的CUDA內核,所以我可以調用從.cpp文件中的內核(不.CU),像這樣:

//kernels.cu: 

//kernel definition 
__global__ void kernelCall_kernel( dataRow* in, dataRow* out, void* additionalData){ 
    //Do something 
}; 

//kernel handler, so I can compile this .cu and link it with the main project and call it within a .cpp file 
extern "C" void kernelCall(dataRow* in, dataRow* out, void* additionalData){ 
    int blocksize = 256; 
    dim3 dimBlock(blocksize); 
    dim3 dimGrid(ceil(tableSize/(float)blocksize)); 
    kernelCall_kernel<<<dimGrid,dimBlock>>>(in, out, additionalData); 

} 

如果我叫處理程序作爲一個正常的函數,打印的數據是正確的。

//streamProcessing.cpp 
//allocations and definitions of data omitted 

//copy data to GPU 
cudaMemcpy(data_d,data_h,tableSize,cudaMemcpyHostToDevice); 
//call: 
kernelCall(data_d,result_d,null); 
//copy data back 
cudaMemcpy(result_h,result_d,resultSize,cudaMemcpyDeviceToHost); 
//show result: 
printTable(result_h,resultSize);// this just iterate and shows the data 

而是讓數據的並行副本並執行在GPU上,我需要創建一個線程,所以當我把它做一個新的boost ::線程:

//allocations, definitions of data,copy data to GPU omitted 
//call: 
boost::thread* kernelThreadOwner = new boost::thread(kernelCall, data_d,result_d,null); 
kernelThreadOwner->join(); 
//Copy data back and print ommited 

我只是得到垃圾當結果打印結果時。

目前我只是使用一個線程,用於測試目的,因此直接調用它或創建一個線程應該沒有太大區別。我不知道爲什麼直接調用函數給出正確的結果,以及創建線程時沒有。這是CUDA &提升的問題嗎?我錯過了什麼嗎?謝謝你的建議。

回答

4

問題在於(CUDA 4.0之前的版本)CUDA上下文與創建它們的線程綁定在一起。當你使用兩個線程時,你有兩個上下文。主線程正在分配和讀取的上下文以及運行內核的線程的上下文不相同。內存分配在上下文之間不可移植。它們實際上是同一GPU內獨立的內存空間。

如果你想以這種方式使用線程,你需要重構一些東西,以便一個線程只與GPU「交談」,並通過CPU內存與父進程通信,或者使用CUDA上下文遷移API,允許上下文從一個線程移動到另一個線程(通過cuCtxPushCurrent和cuCtxPopCurrent)。請注意,上下文遷移不是免費的,並且存在延遲,因此如果您計劃頻繁遷移上下文,則可能會發現切換到保留上下文線程親和性的其他設計會更有效。

+0

謝謝,我會嘗試重新設計 – Vik 2011-05-24 08:53:21

+0

是的,那真的很有用,再次感謝你。我永遠無法通過我自己的方式找出它:) – Vik 2011-05-24 12:37:37

+0

爲什麼你需要多線程才能讓內核執行和cudaMemcpy重疊?這就是cudaMemcpyAsync的用途,對吧? – harrism 2011-05-25 03:14:38