如何在CUDA内核中调用主机函数?

15

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

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

33

很遗憾,在设备上您不能调用未使用__device__修饰符指定的函数。如果您需要在设备代码中使用随机数,请查看CUDA随机生成器curandhttp://developer.nvidia.com/curand

如果您有自己的主机函数要从内核调用,请在其上同时使用__host____device__修饰符:

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

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


2
使用主机函数而不是使用CUDA内置函数会导致性能下降有多严重? - Mattia
这是否意味着主机和设备只会执行它们各自的函数副本? - avgvstvs

7
简短的答案是这个问题没有解决方案。
所有通常在CPU上运行的内容必须为CUDA环境进行定制,而且并不保证可以实现。主机函数在CUDA中只是C语言普通函数的另一个名称。也就是说,所有C / C ++一直以来都是在PC上运行的CPU存储器Von Neumann体系结构。GPU给您提供了巨大的计算能力,但代价是它的灵活性和兼容性远远不如CPU。最重要的是,这些功能在不能访问主内存的情况下运行,它们可以访问的内存也是有限的。
如果你想获取的是随机数生成器,那么你很幸运,因为Nvidia特别实现了一个高效的梅森旋转算法,可以支持每个SMP 256个线程。它可以在设备函数内调用,我之前在这里描述过。如果有人发现更好的链接来描述此功能,请删除我的链接并替换适当的文本及其链接。
我不断被各种编程人员所惊讶的事情之一是他们似乎不知道高质量伪随机数生成器是如何标准化的。"自己动手做"真的不是一个好主意,考虑到伪随机数为多么重要。验证生成器是否提供可接受的不可预测数字需要大量工作和学术才能...

5

虽然不适用于 'rand()',但是在使用计算兼容性>=2.0编译时,一些主机函数如"printf"是可用的。

例如:

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。


-1

我必须在以下方面不同意其他答案:

OP没有描述问题:从设备代码中无法调用__host__函数并不令人遗憾 - 它完全不可能是任何其他方式,这并不是一件坏事。

解释一下:将主机(CPU)代码视为放入CD播放器的CD;将设备代码视为放入微型音乐播放器的SD卡。 OP的问题是“如何将光盘塞入我的微型音乐播放器”?你不能这样做,而且想要这样做毫无意义。它可能本质上是相同的音乐(具有相同功能的代码;尽管通常,主机代码和设备代码不执行完全相同的计算任务)- 但媒体不可互换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接