分离内核。在一个项目中,创建两个文件(我重构了默认的 Runtime Project 模板并创建了 device.cu 和 host.cu)
设备.cu:
__device__ unsigned int bitreverse(unsigned int number) {
number = ((0xf0f0f0f0 & number) >> 4) | ((0x0f0f0f0f & number) << 4);
number = ((0xcccccccc & number) >> 2) | ((0x33333333 & number) << 2);
number = ((0xaaaaaaaa & number) >> 1) | ((0x55555555 & number) << 1);
return number;
}
__global__ void bitreverse(void *data) {
unsigned int *idata = (unsigned int*) data;
idata[threadIdx.x] = bitreverse(idata[threadIdx.x]);
}
主机.cu:
extern __global__ void bitreverse(void *data);
...
bitreverse<<<1, WORK_SIZE, WORK_SIZE * sizeof(int)>>>(d);
单独编译
- 右键单击项目,转到属性。
- 构建/设置。
- 为 SM 2.0 或更高版本设置构建。
- 选择“单独编译”单选。
设备.cu:
__device__ unsigned int bitreverse(unsigned int number) {
number = ((0xf0f0f0f0 & number) >> 4) | ((0x0f0f0f0f & number) << 4);
number = ((0xcccccccc & number) >> 2) | ((0x33333333 & number) << 2);
number = ((0xaaaaaaaa & number) >> 1) | ((0x55555555 & number) << 1);
return number;
}
主机.cu:
extern __device__ unsigned int bitreverse(unsigned int number);
__global__ void bitreverse(void *data) {
unsigned int *idata = (unsigned int*) data;
idata[threadIdx.x] = bitreverse(idata[threadIdx.x]);
}
...
bitreverse<<<1, WORK_SIZE, WORK_SIZE * sizeof(int)>>>(d);
隔离 CUDA 代码一种常见的模式是将 CUDA 代码隔离在 .cu 文件中,这些文件具有封装内核调用的宿主函数。通过这种方式,您可以将此类 .cu 文件生成的目标文件链接到以 .cpp 或 .c 文件编写的主机代码。请记住,导出的主机代码功能应符合extern "C"
.c 文件可用。
extern
声明可以放在 .h 文件中。请注意,具有 CUDA C 语法(__global__
特定于 CUDA C)的 .h 文件不能包含在 .cpp 或 .c 中。
将文件添加到项目
通常我只是将文件复制到项目文件夹,右键单击项目并执行“刷新”。Nsight 将索引它们并包含在构建中。
从构建中排除文件
如果您绝对需要,您可以将设备代码复制到标头并包含标头(惯例是此类头文件具有 .cuh 扩展名,尽管 .h 的工作方式相同)。您可以包含 .cu - 问题是 Nsight 将此类文件视为源文件并尝试编译它们。您可以通过选中构建属性中构建子树中任何属性页面顶部的“从构建中排除资源”复选框来从构建中排除 .cu 文件。
CUDA 多文件示例
几乎所有重要的样本都被分解成多个文件。只需从例如“粒子”示例创建一个 Nsight 项目。