如何以程序员愉快的方式使用CUDA常量内存?

时间:2010-10-24 11:37:51

标签: c++ visual-studio header linker cuda

我正在使用CUDA框架开发一个数字运算应用程序。我有一些静态数据应该可以被所有线程访问,所以我把它放在这样的常量内存中:

__device__ __constant__ CaseParams deviceCaseParams;

我使用调用cudaMemcpyToSymbol将这些参数从主机传输到设备:

void copyMetaData(CaseParams* caseParams)
{
    cudaMemcpyToSymbol("deviceCaseParams", caseParams, sizeof(CaseParams));
}

有效。

无论如何,似乎(通过反复试验,以及在网上阅读帖子),由于某些生病的原因,deviceCaseParams的声明及其复制操作(对cudaMemcpyToSymbol的调用)必须在相同的文件。目前我在.cu文件中有这两个,但我真的想在.cuh文件中使用参数struct,以便任何实现都能看到它。这意味着我还必须在头文件中使用copyMetaData函数,但这会混淆链接(已定义的符号),因为.cpp和.cu文件都包含此头文件(因此MS C ++编译器和nvcc都编译它) )。

有人对此有任何设计建议吗?

更新:查看评论

2 个答案:

答案 0 :(得分:7)

使用最新的CUDA(例如3.2),如果你在运行时查找符号,你应该可以从不同的翻译单元中执行memcpy(即通过将字符串作为第一个arg传递给cudaMemcpyToSymbol就像你的例子一样。)

此外,使用Fermi级设备,您可以将内存(cudaMalloc)malloc,复制到设备内存,然后将参数作为const指针传递。编译器将识别您是否在warp中统一访问数据,如果是,则使用常量缓存。有关详细信息,请参阅“CUDA编程指南”。注意:您需要使用-arch=sm_20进行编译。

答案 1 :(得分:4)

如果您使用的是前费米CUDA,您现在已经发现这个问题不仅适用于常量内存,它适用于您在CUDA方面所需的任何内容。我找到的唯一两种方法是:

  1. 将所有CUDA写入单个文件(.cu)或
  2. 如果您需要将代码分解为单独的文件,请将自己限制为单个.cu文件包含的标题。
  3. 如果您需要在CUDA和C / C ++之间共享代码,或者在项目之间共享一些公共代码,则选项2是唯一的选择。从一开始看起来非常不自然,但它解决了这个问题。您仍然可以构建代码,而不是以典型的C方式。主要的开销是每次进行构建时都要编译所有内容。这方面的优点(我认为这可能是它的工作原理)是CUDA编译器可以访问一次命中的所有源代码,这有利于优化。