我想设计一个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