【发布时间】:2014-12-31 12:23:31
【问题描述】:
我正在尝试设计一个 cuda 框架,该框架将接受用户函数并通过设备函数指针将它们转发到内核。 CUDA 可以与可变参数模板 (-stc=c++11) 一起使用,到目前为止一切正常。
但是,当内核调用设备函数指针时,我遇到了问题。显然内核运行没有问题,但 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 no 回调和 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);
}
【问题讨论】:
-
希望这个答案对您有所帮助。 stackoverflow.com/a/9001502/749973
标签: c++ cuda function-pointers variadic-templates