OpenCl中的标量和向量内核

时间:2013-10-09 23:33:05

标签: vector kernel opencl scalar

我正在阅读本文http://eprints.dcs.warwick.ac.uk/1694/1/miniMD_opencl.pdf关于使用OpenCl的迷你分子动力学应用。代码位于此处。
我对内核的实现方式感到困惑。我不明白的是这个

#if defined(SCALAR_KERNELS)
__kernel void f_clear(
    __global float* f,
    __const int nall) {

    for (unsigned i = get_global_id(0)+1; i <= nall; i += get_global_size(0)) {
        const int i4 = i << 2;
        f[i4+0] = 0.0f;
        f[i4+1] = 0.0f;
        f[i4+2] = 0.0f;
        f[i4+3] = 0.0f;
    }

}
#elif defined(VECTOR_KERNELS)
__kernel __attribute__((vec_type_hint(float4)))
void f_clear(
    __global float4* f,
    __const int nall) {

    const float4 zeroes = (float4) (0.0f, 0.0f, 0.0f, 0.0f);
    for (unsigned i = get_global_id(0)+1; i <= nall; i += get_global_size(0)) {
        f[i] = zeroes;
    }

}
#endif

假设VECTOR_KERNELSSCALAR_KERNELS对应GPU和MIC设备,但不确定 这与MIMD SIMD指令或多核和矢量编程有关吗? 现在使用矢量类型还有一个真正的好处吗?
最后,我真的无法弄清楚两个for循环的作用以及它们的目的 为什么不做f[get_global_id(0)]? 谢谢,
埃里克。

2 个答案:

答案 0 :(得分:3)

标量和向量只是在OpenCL中执行相同操作的不同方式。 但是向量是要走的路,因为编译器(CPU或GPU / FPGA)应该更好地优化它们。这样编译器可以自然地使用SIMD单元。所以,如果有可能并且更容易使用它们,请使用它们。

正如Austin所说,两个循环都清除了nall的全局内存大小。

然而,查看代码是非常低效的。同一工作组中的工作项正在访问完全不同的全局内存区域,从而破坏了合并。 (正如你所说的那样)会好得多:

__kernel __attribute__((vec_type_hint(float4)))
void f_clear(
    __global float4* f) {
    f[get_global_id(0)] = (float4) (0.0f, 0.0f, 0.0f, 0.0f);
}

使用适当的全局大小(global_size = nall)启动此内核,并让编译器决定本地工作组大小。

PS:如果我必须这样做,我更喜欢调用clEnqueueWriteBuffer并从CPU清理内存。因为它可以与其他内核执行并行完成。

答案 1 :(得分:1)

AMD,ATI和Intel等设备非常适合支持矢量类型。这些向量是SIMD,如果可能的话,使用它会更快。在支持OpenCL中的向量时,NVIDIA似乎并不是很好(至少是我测试过的所有内容)。

两个循环似乎都清除了一大块nall的全局内存。