我有一个奇怪的问题,所以我想我会问,看看比我更有经验的人能否找到解决方案。
我正在用CUDA C / C ++编写一个程序,我有一些常量整数来指定各种各样的东西,比如计算边界的坐标等等。目前我只是将这些东西放在全局设备内存中。它们被每个内核调用中的每个线程访问,因此我认为如果它们在全局内存中,那么它们永远不会被缓存或广播(对吧?)。所以这些小整数占用了很多(相对)开销,并且有很多“读取冗余”。
所以我在标题中声明:
__constant__ int* number;
我包含那个标题,当我做内存时,我会这样做:
cutilSafeCall( cudaMemcpyToSymbol(number, &(some_host_int), sizeof(int) );
我将number
传递给我的所有内核:
__global__ void magical_kernel(int* number, ...){
//and I access 'number' like this
int data_thingy = big_array[ *number ];
}
我的代码崩溃了。有了全局内存中的数字,就可以了。我已经确定它在访问内核中的数字时会崩溃。这意味着我正在访问或分配错误。如果它包含错误的值,它也会导致崩溃,因为它用于索引数组。
总而言之,我会问几个问题。首先,我做错了什么?作为奖励:有没有比常量内存更好的方法来完成这项任务 - 我不知道number
在编译时的价值,所以一个简单的#define将不起作用。常量内存甚至可以加快代码的速度,还是一直在高速缓存和广播?我可以以某种方式将数据放在每个线程块的共享内存中,并通过多个内核调用将它保留在共享内存中吗?
答案 0 :(得分:1)
这里有几个问题:
number
声明为指针,但从未为其分配一个值,该值是GPU内存中的有效地址int * number
中定义的参数变量magic_kernel
与定义为编译单元范围的__constant__ int * variable
不是同一个变量。 cudaMemcpyToSymbol
电话的第一个参数几乎肯定不正确。如果你不明白为什么前两点中的任何一个都是真的,你可以对C ++中的指针和范围做一些修改。
根据您对现已删除的答案的回复,我怀疑您实际上要做的是:
__constant__ int number;
__global__ void magical_kernel(...){
int data_thingy = big_array[ number ];
}
cudaMemcpyToSymbol("number", &(some_host_int), sizeof(int));
即。 number
旨在成为常量内存中的整数,而不是指针,而不是内核参数。
编辑:这是一个例子,显示了这一点:
#include <cstdio>
__constant__ int number;
__global__ void magical_kernel(int * out)
{
out[threadIdx.x] = number;
}
int main()
{
const int value = 314159;
const size_t sz = size_t(32) * sizeof(int);
cudaMemcpyToSymbol("number", &value, sizeof(int));
int * _out, * out;
out = (int *)malloc(sz);
cudaMalloc((void **)&_out, sz);
magical_kernel<<<1,32>>>(_out);
cudaMemcpy(out, _out, sz, cudaMemcpyDeviceToHost);
for(int i=0; i<32; i++)
fprintf(stdout, "%d %d\n", i, out[i]);
return 0;
}
您应该能够自己运行并确认它的效果与宣传的一样。