我有一个内核,希望将一些全局数据存储到本地缓冲区以加快速度。我已经获得了很好的结果并缩短了执行时间。为了进一步减少它,我决定修改内核以在一个流中读取这些值。
旧内核:
__local short3 (*lixArr) = (__local short3(*)) (lixInLocal + get_local_id(1) * 3);
__global short (*lab)[TS][TS][3] = (__global short(*)[TS][TS][3]) (buffer + TS*TS*12 + TS*TS*26*get_global_id(2));
__global short3 (*lix) = (__global short3(*)) (lab[0][get_global_id(0)+2][1+get_global_id(1)]);
lixArr[1] = lix[0].xyz;
lixArr[2] = lix[-TS].xyz;
lixArr[3] = lix[TS].xyz;
if(get_local_id(1) == 0)
lixArr[0] = lix[-1].xyz;
else if(get_local_size(1) == get_local_id(1)+1)
lixArr[3+1] = lix[1].xyz;
lix = (__global short(*)) (lab[1][get_global_id(0)+2][1+get_global_id(1)]);
lixArr += (get_local_size(1))*3 + 2;
lixArr[1] = lix[0].xyz;
lixArr[2] = lix[-TS].xyz;
lixArr[3] = lix[TS].xyz;
if(get_local_id(1) == 0)
lixArr[0] = lix[-1].xyz;
else if(get_local_size(1) == get_local_id(1)+1)
lixArr[3+1] = lix[1].xyz;
barrier(CLK_LOCAL_MEM_FENCE);
修改后的流读取:
__global short (*lab)[TS][TS][3] = (__global short(*)[TS][TS][3]) (buffer + TS*TS*12 + TS*TS*26*get_global_id(2));
__global short3 (*lix) = (__global short3(*)) (lab[(get_local_id(1) % 6 > 2)][get_global_id(0)+2][1+(get_local_id(1)/3)*6]);
__global short16 (*lix16);
__local short16 (*lixLocal16);
lix16 = (__global short16(*)) (&lix[(get_local_id(1) % 3 == 0) ? 0 : (get_local_id(1) % 3 == 1) ? -TS : TS]);
lixLocal16 = (__local short16(*)) (lixInLocal + ((get_local_id(1) % 6) * (get_local_size(1)+2) + 1 + (get_local_id(1) /6)*6));
lixLocal16[0] = lix16[0].s0123456789ABCDEF;
lixLocal16[1].s01 = lix16[1].s01;
if((get_local_id(1) % 3 + get_local_id(1) / 6) == 0)
lixInLocal[(get_local_id(1) % 6) * (get_local_size(1)+2)] = lix[-1].xyz;
else if(get_local_id(1) % 3 == 0 && get_local_id(1)+6 >= get_local_size(1))
lixInLocal[(get_local_id(1) % 6) * (get_local_size(1)+2)-1] = lix[1].xyz;
mem_fence(CLK_LOCAL_MEM_FENCE);
在第一个内核中,如您所见,我读取了远处的值。在第二种情况下,我修改了内核以读取18个后续值而不是6 * 3分离。
有一点可能很重要 - 在第一种情况下,稍后会使用读取值。在第二个中仅使用1,其他用于另一个WorkItem。
我也试过使用vstoren和vloadn,但结果更糟。
最后一个问题:为什么这些后续读取会如此迅速地增加执行时间,何时应该加快速度?