CUDA常量内存值不正确

CUDA常量内存值不正确,cuda,nvcc,Cuda,Nvcc,我已经阅读了很多关于恒定记忆的问题,但我仍然不明白为什么我的程序不能工作。总的来说,情况如下 普通。cuh __constant__ int numElements; __global__ void kernelFunction(); 普通.cu #include "Common.cuh" #include <stdio.h> __global__ kernelFunction() { printf("NumElements = %d", numElements); }

我已经阅读了很多关于恒定记忆的问题,但我仍然不明白为什么我的程序不能工作。总的来说,情况如下

普通。cuh

__constant__ int numElements;

__global__
void kernelFunction();
普通.cu

#include "Common.cuh"
#include <stdio.h>

__global__
kernelFunction()
{
   printf("NumElements = %d", numElements);
}
#include "Common.cuh"

int main()
{
   int N = 100;
   cudaMemcpyToSymbol(numElements,&N,sizeof(int));
   kernelFunction<<<1,1>>>();
   cudaDeviceSynchronize();
   return 0;
}
#包括“Common.cuh”
#包括
__全球的__
核函数()
{
printf(“NumElements=%d”,NumElements);
}
测试.cu

#include "Common.cuh"
#include <stdio.h>

__global__
kernelFunction()
{
   printf("NumElements = %d", numElements);
}
#include "Common.cuh"

int main()
{
   int N = 100;
   cudaMemcpyToSymbol(numElements,&N,sizeof(int));
   kernelFunction<<<1,1>>>();
   cudaDeviceSynchronize();
   return 0;
}
#包括“Common.cuh”
int main()
{
int N=100;
cudaMemcpyToSymbol(numElements,&N,sizeof(int));
核函数();
cudaDeviceSynchronize();
返回0;
}
它编译时没有错误,但在打印
numElements
的值时,我只得到一个随机值。有人能给我指出正确的方向来理解这一点吗?

这一行:

__constant__ int numElements;
具有编译单元范围。这意味着,如果您将它编译成一个模块,也编译成另一个模块,那么这两个模块将在
\uuuu constant\uuu
内存中具有不同的
numElements
实例化

解决方案是使用设备将两个模块链接在一起,此时,符号将由设备链接器在两个模块之间解析

nvcc -arch=sm_20 -rdc=true -o test common.cu test.cu
例如:

$ cat common.cuh
#ifndef COMMON_CU
extern __constant__ int numElements;
#endif
__global__
void kernelFunction();
$ cat common.cu
#define COMMON_CU
#include "common.cuh"
#include <stdio.h>

__constant__ int numElements;
__global__
void kernelFunction()
{
   printf("NumElements = %d\n", numElements);
}
$ cat test.cu
#define TEST_CU
#include "common.cuh"

int main()
{
   int N = 100;
   cudaMemcpyToSymbol(numElements,&N,sizeof(int));
   kernelFunction<<<1,1>>>();
   cudaDeviceSynchronize();
   return 0;
}

$ nvcc -arch=sm_20 -rdc=true -o test common.cu test.cu
$ ./test
NumElements = 100
$
$cat common.cuh
#ifndef普通铜
外部常数;
#恩迪夫
__全球的__
void kernelFunction();
$cat common.cu
#定义公共_CU
#包括“common.cuh”
#包括
__恒定整数;
__全球的__
void kernelFunction()
{
printf(“NumElements=%d\n”,NumElements);
}
$cat test.cu
#定义测试单元
#包括“common.cuh”
int main()
{
int N=100;
cudaMemcpyToSymbol(numElements,&N,sizeof(int));
核函数();
cudaDeviceSynchronize();
返回0;
}
$nvcc-arch=sm_20-rdc=true-o test common.cu test.cu
美元/测试
整数=100
$
此行:

__constant__ int numElements;
具有编译单元范围。这意味着,如果您将它编译成一个模块,也编译成另一个模块,那么这两个模块将在
\uuuu constant\uuu
内存中具有不同的
numElements
实例化

解决方案是使用设备将两个模块链接在一起,此时,符号将由设备链接器在两个模块之间解析

nvcc -arch=sm_20 -rdc=true -o test common.cu test.cu
例如:

$ cat common.cuh
#ifndef COMMON_CU
extern __constant__ int numElements;
#endif
__global__
void kernelFunction();
$ cat common.cu
#define COMMON_CU
#include "common.cuh"
#include <stdio.h>

__constant__ int numElements;
__global__
void kernelFunction()
{
   printf("NumElements = %d\n", numElements);
}
$ cat test.cu
#define TEST_CU
#include "common.cuh"

int main()
{
   int N = 100;
   cudaMemcpyToSymbol(numElements,&N,sizeof(int));
   kernelFunction<<<1,1>>>();
   cudaDeviceSynchronize();
   return 0;
}

$ nvcc -arch=sm_20 -rdc=true -o test common.cu test.cu
$ ./test
NumElements = 100
$
$cat common.cuh
#ifndef普通铜
外部常数;
#恩迪夫
__全球的__
void kernelFunction();
$cat common.cu
#定义公共_CU
#包括“common.cuh”
#包括
__恒定整数;
__全球的__
void kernelFunction()
{
printf(“NumElements=%d\n”,NumElements);
}
$cat test.cu
#定义测试单元
#包括“common.cuh”
int main()
{
int N=100;
cudaMemcpyToSymbol(numElements,&N,sizeof(int));
核函数();
cudaDeviceSynchronize();
返回0;
}
$nvcc-arch=sm_20-rdc=true-o test common.cu test.cu
美元/测试
整数=100
$

仅当Common.cu使用常量变量
numElements
时,此功能正常。但是,如果我想在Test.cu中也使用常量变量,我会得到
nvlin错误:“numElements”的多个定义
也许你应该仔细阅读答案并发布代码。test.cu确实使用相同的常量变量,因为它是对常量变量进行写入的,并且是调用
kernelFunction
的。多重定义错误是因为
numElements
只能在一个位置定义。其他地方必须通过
extern
引用它。请仔细阅读答案。请注意,我的答案与您的代码的区别不仅仅在于编译命令。此外,我已将
numElements
的定义从头文件移出,并移到一个源文件(
common.cu
)中。在我的头文件(
common.cuh
)中,它仅指由
extern
创建的
numElements
,并且仅当该头文件包含在
common.cu
以外的文件中时。因此,我的答案和你的答案之间存在代码更改,而不仅仅是编译命令的差异。如标记的重复问题/答案所示,还可以通过将
numElements
的定义和所有显式引用移动到单个文件中来解决此问题。对其他文件(即编译单元或模块)中的
numElements
的所有操作必须通过在定义
numElements
的文件中定义的包装函数间接进行。这种方法不需要模块之间的设备代码链接。对不起,我通常不聊天。此外,我对CMake几乎一无所知。我的目的不仅仅是帮助你,而是帮助那些通过谷歌或其他方式找到答案的人。(聊天根本帮不上忙。)由于您的基本示例有效,并且您现在收到的错误看起来完全不同,我建议发布一个新的SO问题。仅当Common.cu使用常量变量
numElements
时,该问题就行了。但是,如果我想在Test.cu中也使用常量变量,我会得到
nvlin错误:“numElements”的多个定义
也许你应该仔细阅读答案并发布代码。test.cu确实使用相同的常量变量,因为它是对常量变量进行写入的,并且是调用
kernelFunction
的。多重定义错误是因为
numElements
只能在一个位置定义。其他地方必须通过
extern
引用它。请仔细阅读答案。请注意,我的答案与您的代码的区别不仅仅在于编译命令。此外,我已将
numElements
的定义从头文件移出,并移到一个源文件(
common.cu
)中。在我的头文件(
common.cuh
)中,它仅指由
extern
创建的
numElements
,并且仅当该头文件包含在
common.cu
以外的文件中时。所以我的答案和你的答案之间有代码变化,而不仅仅是编译命令的差异