有人能描述一下 __global__
和 __device__
之间的区别吗?
何时应该使用 __device__
,何时应该使用 __global__
?
有人能描述一下 __global__
和 __device__
之间的区别吗?
何时应该使用 __device__
,何时应该使用 __global__
?
全局函数也被称为"内核"。它是您可以使用CUDA内核调用语义(<<<...>>>
)从主机端调用的函数。
设备函数只能从其他设备或全局函数中调用。__device__
函数不能从主机代码中调用。
__global__
- 运行在 GPU 上,可以从 CPU 或 GPU 调用*. 使用 <<<dim3>>>
参数执行。__device__
- 运行在 GPU 上, 可以从 GPU 调用. 也可用于变量。__host__
- 运行在 CPU 上, 只能从 CPU 调用。*) 只有当计算能力达到 3.5 或以上时,__global__
函数才能被其他 __global__
函数调用。
__device__
和 __global__
函数的区别如下:
__device__
函数只能从设备调用,且仅在设备上执行。
__global__
函数可以从主机调用,但在设备上执行。
因此,您可以从内核函数中调用 __device__
函数,并且不必设置内核设置。您还可以“重载”一个函数,例如:您可以声明 void foo(void)
和 __device__ foo (void)
,其中一个在主机上执行并且只能从主机函数调用。另一个在设备上执行,并且只能从设备或内核函数调用。
您也可以访问以下链接:http://code.google.com/p/stanford-cs193g-sp2010/wiki/TutorialDeviceFunctions,这对我很有帮助。
我将通过一个例子来解释:
main()
{
// Your main function. Executed by CPU
}
__global__ void calledFromCpuForGPU(...)
{
//This function is called by CPU and suppose to be executed on GPU
}
__device__ void calledFromGPUforGPU(...)
{
// This function is called by GPU and suppose to be executed on GPU
}
也就是说,当我们想要一个主机(CPU)函数调用一个设备(GPU)函数时,我们使用“global”。请阅读:https://code.google.com/p/stanford-cs193g-sp2010/wiki/TutorialGlobalFunctions
而当我们想要一个设备(GPU)函数(即核函数)调用另一个核函数时,我们使用“device”。请阅读:https://code.google.com/p/stanford-cs193g-sp2010/wiki/TutorialDeviceFunctions
这应该足以理解它们之间的区别。
__global__
是用于 CUDA kernel 的关键字,表示可以直接从主机上调用的函数。而 __device__
函数可以被 __global__
和 __device__
函数调用,但不能从主机上调用。
__global__
函数是核心函数的定义。每当它从CPU调用时,该核心就会在GPU上启动。
但是,执行该核心的每个线程可能需要再次执行某些代码,例如交换两个整数。因此,在这里我们可以编写一个辅助函数,就像在C程序中一样。对于在GPU上执行的线程,应将辅助函数声明为__device__
。
因此,设备函数从核心的线程中调用-每个线程实例调用一次。而全局函数从CPU线程中调用。
我在这里记录一些无根据的猜测(当我找到一些权威来源时,我将对这些内容进行证实)...
__device__
函数可以返回void以外的类型,但是__global__
函数必须始终返回void。
__global__
函数可以从GPU上运行的其他内核中调用,以启动附加的GPU线程(作为CUDA动态并行性模型(又名CNP)的一部分),而__device__
函数在调用内核相同的线程上运行。
__global__
是 CUDA C 的关键字(声明说明符),表示函数:
使用 <<< no_of_blocks , no_of threads_per_block>>>
从主机代码启动全局函数(内核)。每个线程通过其唯一的线程 ID 执行内核。
但是,__device__
函数无法从主机代码中调用。如果需要这样做,请同时使用 __host__
和 __device__
。
全局函数只能从主机调用,它们没有返回类型;设备函数只能从其他设备函数或内核函数中调用,因此不需要内核设置。
__global__
函数也可以使用CUDA内核语义(<<<...>>>)从设备上调用,这需要CUDA 5.0和计算能力3.5或更高。 - Tom