如何在CUDA内核中调用主机功能?

时间:2012-03-30 03:52:53

标签: cuda gpgpu

如下面的错误所示,内核中不允许调用主机函数('rand'),如果我确实需要这样做,我想知道是否有解决方案。

error: calling a host function("rand") from a __device__/__global__ function("xS_v1_cuda") is not allowed

4 个答案:

答案 0 :(得分:27)

很遗憾,您无法调用未使用__device__修饰符指定的设备中的函数。如果您需要设备代码中的随机数字,请查看cuda random generator curand http://developer.nvidia.com/curand

如果您有自己想要从内核调用的主机功能,请同时使用__host____device__修饰符:

__host__ __device__ int add( int a, int b )
{
    return a + b;
}

当这个文件由NVCC编译器驱动程序编译时,会编译两个版本的函数:一个可以通过主机代码调用,另一个可以通过设备代码调用。这就是为什么现在可以通过主机和设备代码调用此函数的原因。

答案 1 :(得分:7)

简短的回答是,这个问题没有解决办法。

通常在CPU上运行的所有内容都必须针对CUDA环境进行定制,而不保证甚至可以做到。主机函数只是CUDA中普通C函数的另一个名称。也就是说,在所有C / C ++上运行在CPU内存Von Neumann架构上的功能已经达到PC的这一点。 GPU为您提供了巨大的计算能力,但成本却不是那么灵活或兼容。最重要的是,这些函数在没有访问主内存的情况下运行,并且它们可以访问的内存是有限的。

如果你想得到的是一个随机数生成器你很幸运,考虑到Nvidia遇到了专门实现高效Mersenne Twister的麻烦,每个SMP最多可以支持256个线程。它可以在设备函数中调用,在我的早期帖子[{3}}中描述。如果有人找到描述此功能的更好链接,请删除我的并在此处替换相应的文本以及链接。

我不断惊讶的一件事是,有多少程序员似乎不知道标准化的高质量伪随机数生成器是多么的。考虑到有多少艺术伪随机数,“滚动你自己”真的不是一个好主意。验证发电机提供可接受的不可预测的数字需要大量的工作和学术才能......

答案 2 :(得分:5)

虽然不适用于'rand()',但在使用计算兼容性> = 2.0进行编译时,可以使用一些主机函数,例如“printf”

e.g:

nvcc.exe -gencode=arch=compute_10,code=\sm_10,compute_10\...
error : calling a host function("printf") from a __device__/__global__ function("myKernel") is not allowed

编译并使用sm_20,compute_20

答案 3 :(得分:-2)

我必须在以下意义上不同意其他一些答案:

OP 没有描述问题:不幸的是你不能从设备代码中调用__host__函数 - 它完全不可能是任何其他方式,而这不是一件坏事。

解释:想想你放入CD播放器的主机(CPU)代码,如CD;并且在设备代码上,比如SD卡,你放入一个微型音乐播放器。 OP的问题是“如何将光盘推入我的微型音乐播放器”?你不能,也没有意义。它本质上可能是相同的音乐(具有相同功能的代码;虽然通常,主机代码和设备代码不执行完全相同的计算任务) - 但媒体不可互换。