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



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

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

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

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

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

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

简单的答案是没有解决这个问题的方法。

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

如果你想要的是一个随机数生成器,那么你很幸运,因为Nvidia专门实现了一个高效的Mersenne Twister,每个SMP最多可以支持256个线程。它可以在设备函数中调用,我在这里的早期文章中对此进行了描述。如果有人找到了描述此功能的更好链接,请删除我的链接,并将此处的相应文本与链接一起替换。

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

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

例如:

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

我不得不从以下意义上不同意其他一些答案:

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

解释一下:把主机(CPU)代码想象成你放进CD播放器的CD;以及设备代码,比如说,SD卡,你可以把它放进一个微型音乐播放器里。OP的问题是"我怎么能把一张光盘塞进我的微型音乐播放器"?你不能,想要也没有意义。它可能本质上是相同的音乐(具有相同功能的代码;尽管通常情况下,主机代码和设备代码执行的计算任务并不完全相同),但媒体是不可互换的。

最新更新