在不同的源文件上使用相同的常量内存数组

时间:2014-03-12 10:32:20

标签: cuda

我有一个__constant__内存数组,其中包含许多内核所需的信息,这些内核放在不同的源文件中。此常量内存数组在标头GlobalParameters.h中定义,所有包含需要访问此数组的内核的文件都为#included

just discovered(看看talonmies'回答)__constant memory__仅在定义它的翻译单元中可用,除非您打开单独的编译(使用CUDA 5.0或后来)。

我仍然没有完全了解这对我的情况意味着什么。

假设我无法启用单独的编译,是否有办法处理我的需求?我应该在哪里放置我的常量内存数组的定义?如果我将它放在我的标题中,在许多翻译单元中#included怎么办?

假设我可以打开单独的编译,我应该将标头中的__constant__内存数组声明为extern并将定义放在源文件中(例如GlobalParameters.cu)?

4 个答案:

答案 0 :(得分:2)

使常量内存可用于除声明它之外的转换单元的一种方法是调用cudaGetSymbolAddress()并使指针可用于其他函数。

这种技术在某种程度上起了作用,因为如果你使用指针在没有适当的障碍和同步的情况下写入内存,你可能会因常量内存和全局内存之间缺乏一致性而受到冲击。

此外,如果使用此方法,则可能无法获得常量内存的全部性能优势。在SM 2.x和更高版本的硬件上应该不那么真实 - 反汇编目标代码并确保编译器正在发出"加载均匀"指令。

答案 1 :(得分:1)

以下示例假定使用单独编译的可能性。在这种情况下,下面的示例显示了如何使用#include "cuda_runtime.h" #include "device_launch_parameters.h" #include <stdio.h> #include "Utilities.cuh" __constant__ int N_GPU; __constant__ float a_GPU; __global__ void printKernel(); int main() { const int N = 5; const float a = 10.466; gpuErrchk(cudaMemcpyToSymbol(N_GPU, &N, sizeof(int))); gpuErrchk(cudaMemcpyToSymbol(a_GPU, &a, sizeof(float))); printKernel << <1, 1 >> > (); gpuErrchk(cudaPeekAtLastError()); gpuErrchk(cudaDeviceSynchronize()); return 0; } 在不同的编译单元中使用常量内存。

FILE kernel.cu

#include <stdio.h>

extern __constant__ int     N_GPU;
extern __constant__ float   a_GPU;

__global__ void printKernel() {

    printf("N = %i; a = %f\n", N_GPU, a_GPU);

}

FILE otherCompilationUnit.cu

display:inline-block

答案 2 :(得分:0)

不,如果不使用单独的编译,就不可能在几个.cu文件中使用相同的常量内存,即一次声明。

在我的观点中,有两种解决方法。
第一个是在一个.cu文件中实现所有内核。因此,您将会遇到这样一个缺点:这个文件会因为概览错误而变得非常大。

第二种方法是在每个.cu文件中再次声明常量内存。然后,使用包装器将值复制到每个.cu文件的常量内存中 - 就像我在回答here中所描述的那样。缺点是您必须确保不要忘记在单个.cu文件中复制值,并且必须检查您是否不会在总可用常量内存的限制中运行。

答案 3 :(得分:0)

是的。后来的CUDA文档说: 在单独的编译模式下编译时(有关此模式的说明,请参见nvcc用户手册),设备共享托管 constant 变量定义为外部变量。如果nvlink找不到外部变量的定义(除非它是动态分配的 shared 变量),它将生成错误。