【发布时间】:2013-03-25 20:56:22
【问题描述】:
我正在处理一个结构数组,并且我希望每个块都将共享内存加载到数组的一个单元格中。例如:block 0 将在共享内存中加载 array[0],block 1 将加载 array[1]。
为了做到这一点,我将结构数组转换为 float* 以尝试合并内存访问。
我有两个版本的代码
版本 1
__global__
void load_structure(float * label){
__shared__ float shared_label[48*16];
__shared__ struct LABEL_2D* self_label;
shared_label[threadIdx.x*16+threadIdx.y] =
label[blockIdx.x*sizeof(struct LABEL_2D)/sizeof(float) +threadIdx.x*16+threadIdx.y];
shared_label[(threadIdx.x+16)*16+threadIdx.y] =
label[blockIdx.x*sizeof(struct LABEL_2D)/sizeof(float) + (threadIdx.x+16)*16+threadIdx.y];
if((threadIdx.x+32)*16+threadIdx.y < sizeof(struct LABEL_2D)/sizeof(float)) {
shared_label[(threadIdx.x+32)*16+threadIdx.y] =
label[blockIdx.x*sizeof(struct LABEL_2D)/sizeof(float) +(threadIdx.x+32)*16+threadIdx.y];
}
if(threadIdx.x == 0){
self_label = (struct LABEL_2D *) shared_label;
}
__syncthreads();
return;
}
...
dim3 dimBlock(16,16);
load_structure<<<2000,dimBlock>>>((float*)d_Label;
计算时间:0.740032 毫秒
第 2 版
__global__
void load_structure(float * label){
__shared__ float shared_label[32*32];
__shared__ struct LABEL_2D* self_label;
if(threadIdx.x*32+threadIdx.y < *sizeof(struct LABEL_2D)/sizeof(float))
shared_label[threadIdx.x*32+threadIdx.y] =
label[blockIdx.x*sizeof(struct LABEL_2D)/sizeof(float)+threadIdx.x*32+threadIdx.y+];
if(threadIdx.x == 0){
self_label = (struct LABEL_2D *) shared_label;
}
__syncthreads();
return;
}
dim3 dimBlock(32,32);
load_structure<<<2000,dimBlock>>>((float*)d_Label);
计算时间:2.559264 毫秒
在这两个版本中,我都使用了 nvidia profiler,全局负载效率为 8%。
我有两个问题: 1 - 我不明白为什么会有时间差异。 2 - 我的通话是否合并?
我正在使用具有 2.1 计算能力(32 线程/环绕)的显卡
【问题讨论】:
-
编译器可能会在消除无用代码的意义上进行优化。因此,由于您的线程实际上对全局内存没有影响,编译器可以消除代码,并且当您在第二个中执行四倍多的线程时,您会得到 app.计算时间增加四倍。检查编译器的 ptx-output 以确认我的假设。