我在这里呈现一些代码
__constant__ int array[1024];
__global__ void kernel1(int *d_dst) {
int tId = threadIdx.x + blockIdx.x * blockDim.x;
d_dst[tId] = array[tId];
}
__global__ void kernel2(int *d_dst, int *d_src) {
int tId = threadIdx.x + blockIdx.x * blockDim.x;
d_dst[tId] = d_src[tId];
}
int main(int argc, char **argv) {
int *d_array;
int *d_src;
cudaMalloc((void**)&d_array, sizeof(int) * 1024);
cudaMalloc((void**)&d_src, sizeof(int) * 1024);
int *test = new int[1024];
memset(test, 0, sizeof(int) * 1024);
for (int i = 0; i < 1024; i++) {
test[i] = 100;
}
cudaMemcpyToSymbol(array, test, sizeof(int) * 1024);
kernel1<<< 1, 1024 >>>(d_array);
cudaMemcpy(d_src, test, sizeof(int) * 1024, cudaMemcpyHostToDevice);
kernel2<<<1, 32 >>>(d_array, d_src),
free(test);
cudaFree(d_array);
cudaFree(d_src);
return 0;
}
这只是显示了常量内存和全局内存的使用情况。在执行过程中,“kernel2”比“kernel1”快大约4倍(根据时间计算)。
根据Cuda C编程指南,我理解这是因为对常量内存的访问被序列化。这让我想到,如果一个warp访问单个常量值(如整数、浮点数、双精度等),那么可以最好地利用常量内存,但是访问数组则没有任何好处。换句话说,为了从常量内存访问中获得任何有益的优化/加速收益,一个warp必须访问单个地址。这样说正确吗?
我还想知道,如果我在常量内存中保留一个结构而不是一个简单类型。在warp内部的线程访问结构的任何位置是否也被视为单个内存访问或多个内存访问?我的意思是,结构可能包含多个简单类型和数组;当访问这些简单类型时,这些访问是否也被序列化?
最后一个问题是,如果我有一个包含常量值的数组,需要由warp内的不同线程访问;为了更快地访问,它应该放在全局内存中而不是常量内存中。这正确吗?
有人能给我推荐一些演示有效使用常量内存的示例代码吗?
问候,
struct Simple { int a, int b, int c}
。如果我按顺序访问这些简单类型,例如p = s.a + s.b + s.c
,并且所有线程都在一个warp中执行此代码,则对这些变量的访问是否被串行化? - Psypher