连续读取比更远更慢?

时间:2013-01-26 13:04:46

标签: c++ opencl

我有一个内核,希望将一些全局数据存储到本地缓冲区以加快速度。我已经获得了很好的结果并缩短了执行时间。为了进一步减少它,我决定修改内核以在一个流中读取这些值。

旧内核:

__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。

  • 在第一种情况下,内核执行平均为28.5ms。
  • 在第二种情况下执行需要96ms!

我也试过使用vstoren和vloadn,但结果更糟。

最后一个问题:为什么这些后续读取会如此迅速地增加执行时间,何时应该加快速度?

0 个答案:

没有答案