我想設計一個cuda框架,它將接受用戶函數並通過設備函數指針將它們轉發給內核。 CUDA可以使用可變參數模板(-stc = C++ 11),並且非常好。CUDA內核與函數指針和可變參數模板
但是,當內核調用設備函數指針時出現問題。顯然內核運行沒有問題,但GPU使用率爲0%。如果我簡單地用實際函數替換回調指針,那麼GPU使用率爲99%。這裏的代碼非常簡單,大的循環範圍僅僅是爲了使事情可以測量。我測與GPU狀態:
nvidia-smi --query-gpu=utilization.gpu,utilization.mory,memory.used --format=csv -lms 100 -f out.txt
IIRC,用戶功能需要在同一個文件爲單位的內核(可能是執行#included)以NVCC成功。 func_d就在源代碼中,並且它編譯並運行良好,除了不使用函數指針(這是本設計中的全部要點)。
我的問題是: 爲什麼帶回調設備函數指針的內核不工作?
需要注意的是,當我printf的諾斯回調和func_d地址,它們是相同的,因爲在此示例輸出:
size of Args = 1
callback() address = 4024b0
func_d() address = 4024b0
另一個奇怪的是,如果取消註釋在kernel()
的callback()
呼叫,則GPU使用率回到0%,即使func_d()
調用仍然在那裏... func_d版本需要大約4秒鐘的運行時間,而回調版本不需要任何(約0.1秒)。
系統規格和編譯命令位於以下代碼的頭部。
謝謝!
// compiled with:
// nvcc -g -G -O0 -std=c++11 -arch=sm_20 -x cu sample.cpp
//
// Nvidia Quadro 6000 (compute capability 2.0)
// CUDA 6.5 (V6.5.12),
// Arch Linux, Nvidia driver 343.22-4, gcc 4.9.1
// Nov, 2014
#include <stdio.h>
__device__
void func_d(double* vol)
{
*vol += 5.4321f;
}
// CUDA kernel function
template <typename... Types>
__global__ void kernel(void (*callback)(Types*...))
{
double val0 = 1.2345f;
// // does not use gpu (0% gpu utilization)
// for (int i = 0; i < 1000000; i++) {
// callback(&val0);
// }
// uses gpu (99% gpu utilization)
for (int i = 0; i < 10000000; i++) {
func_d(&val0);
}
}
// host function
template <typename... Types>
void host_func(void (*callback)(Types*...))
{
// get user kernel number of arguments.
constexpr int I = sizeof...(Types);
printf("size of Args = %d\n",I);
printf("callback() address = %x\n",callback);
printf("func_d() address = %x\n",func_d);
dim3 nblocks = 100;
int nthread = 100;
kernel<Types...><<<nblocks,nthread>>>(callback);
}
__host__
int main(int argc, char** argv)
{
host_func(func_d);
}
希望這個答案可以幫助你。 http://stackoverflow.com/a/9001502/749973 – 2014-11-04 23:26:27