在CUDA中,函数类型限定符__device__
和__host__
可以一起使用,在这种情况下,将为主机和设备编译函数。这允许消除复制粘贴。但是,没有__host__ __device__
变量这样的东西。我正在寻找一种优雅的方式来做这样的事情:
__host__ __device__ const double common = 1.0;
__host__ __device__ void foo() {
... access common
}
__host__ __device__ void bar() {
... access common
}
我发现以下代码符合并运行且没有错误。 (所有结果均在Ubuntu 14.04上获得,CUDA 7.5和gcc 4.8.4作为主编译器)
#include <iostream>
__device__ const double off = 1.0;
__host__ __device__ double sum(int a, int b) {
return a + b + off;
}
int main() {
double res = sum(1, 2);
std::cout << res << std::endl;
cudaDeviceReset();
return 0;
}
$ nvcc main.cu -o main && ./main
4
事实上,nvcc --cuda main.cu
将cu文件转换为:
...
static const double off = (1.0);
# 5 "main.cu"
double sum(int a, int b) {
# 6 "main.cu"
return (a + b) + off;
# 7 "main.cu"
}
# 9 "main.cu"
int main() {
# 10 "main.cu"
double res = sum(1, 2);
# 11 "main.cu"
(((std::cout << res)) << (std::endl));
# 12 "main.cu"
cudaDeviceReset();
# 13 "main.cu"
return 0;
# 14 "main.cu"
}
...
但是,毫不奇怪,如果声明变量off
没有const
限定符(__device__ double off = 1.0
),我会得到以下输出:
$ nvcc main.cu -o main && ./main
main.cu(7): warning: a __device__ variable "off" cannot be directly read in a host function
3
那么,回到原来的问题,我可以依靠全局__device__ const
变量的这种行为吗?如果没有,还有其他选择吗?
UPD 顺便说一下,上述行为在Windows上无法重现。
答案 0 :(得分:6)
对于普通浮点或整数类型,仅在全局范围内将变量标记为const
就足够了:
const double common = 1.0;
然后它应该可用于任何后续功能,无论是主持人,__host__
,__device__
还是__global__
。
文档here支持此功能,但受各种限制:
让'V'表示命名空间作用域变量或具有 const 限定类型且没有执行空间注释的类静态成员变量(例如
__device__
,{{1} },__constant__
)。 V被认为是主机代码变量。V的值可以直接用在设备代码中,如果 V在使用点之前已经用常量表达式初始化,并且 它有以下类型之一:
- 内置浮点类型,除非将Microsoft编译器用作主机编译器,
- 内置整体式。
设备源代码不能包含对V的引用或取V的地址。
在其他情况下,一些可能的选择是:
使用编译器宏定义的常量:
__shared__
如果变量的选择范围是离散且有限的,则使用模板。
对于其他选项/案例,可能需要管理变量的显式主机和设备副本,例如:在设备上使用#define COMMON 1.0
内存,在主机上使用相应的副本。访问变量的__constant__
__host__
函数中的主机和设备路径可以根据nvcc编译器宏来区分行为(例如__device__