OpenCL:long,long4,long16 ......何时使用?

时间:2012-02-07 11:59:29

标签: opencl gpgpu

我正在尝试理解使用long,long2,long3,long4,long8,long16之间的区别。我们假设我的CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG是2。

我应该何时使用long,long2,long3,long4,long8,long16?假设我希望我的内核对一堆bitvectors进行异或,例如,长度为500.

  • 如果使用很长时间,我需要XOR ceil(500/64)= 8长。
  • 如果使用long2,我需要XOR ceil(500/128)= 4 long2。
  • 如果使用long8,我需要XOR ceil(500/512)= 1 long8。

那么xorring long [8],long2 [4]还是long8之间的区别是什么?是否有超越CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG的优势?

编辑:我添加了一个小样本脚本以使其更清晰:for (int j=0; j<8; j++)遍历长度为8的向量,我想知道我是否最好为一个long8执行此操作,四个long2 s或8 long s。

while (i < to) {
    ui64[] row = rows[rowIndex];
    ui64 bitchange = i++;
    bitchange ^= i;
    rowIndex = 63-__builtin_clzll(bitchange);
    ui64 cardinality = 0;
    for (int j=0; j<8; j++) {
        curr[j] ^= row[j];
        cardinality += __builtin_popcountll(curr[j]);
    }
    popcountpolynomial[cardinality]++;
}

2 个答案:

答案 0 :(得分:1)

任何数据类型的CL_DEVICE_PREFERRED_VECTOR_WIDTH_(类型)通常是内存访问的最有效大小。许多当前的GPU设备使用128位高速缓存行结构,这就是CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG经常评估为2的原因。如果使用long4,则内存操作可能会被分解为设备上的两个较小的读/写 - 有效地阻止某些线程执行。我不认为使用大于首选尺寸的矢量是有利的,但我可以想象一个缺点。您应该在设备上对其进行基准测试,看看这是否适合您。

如果您正在进行的唯一操作是XOR,我建议使用longN(N =首选大小)和64位原子来完成工作。我希望你的设备支持64位扩展原子。 (cl_khr_int64_extended_atomics)

答案 1 :(得分:1)

mfa对于首选宽度是正确的,但使用更宽的向量通常是好的。设备将按顺序发出指令,以便在其支持的最宽格式向量中处理,这很好,因为它有助于隐藏操作的延迟。这在GPU上更是如此,而在CPU上则更为真实,GPU往往有很多寄存器(> 1000)。

将首选宽度视为宽度,以确保您不会“浪费”矢量架构处理器上的矢量通道 - 如果GPU具有矢量ALU,则发出不使用整个宽度的指令(例如,仅使用向量中的第一项,然后其他通道可能在该指令中未使用,浪费了潜在的计算能力。想想SSE在哪里可以用一条指令做4次加法,但是你只得到一个数字,因为你没有使用4个向量中的3个。

如果你没有使用完整的矢量宽度,OpenCL编译器(在矢量ALU硬件上)尝试将你的代码重组为“矢量化”,但显然存在限制。

当然,只有在算法中感觉自然时才使用更宽的向量。永远不要扭曲你的程序,试图使用真正宽的载体。

使用较少的寄存器也是一件好事,如果你使用太多的寄存器,它可能会限制可以并行运行的波前/扭曲的数量。

如果自动矢量化器无法在标量代码中找到矢量化解决方案,使用矢量实际上可以降低寄存器压力,在硬件确实使用矢量ALU的情况下 - 您将“浪费”更少的矢量通道,因为更多适合在每个登记册中。