Vector OpenCl中的标量核和向量核

Vector OpenCl中的标量核和向量核,vector,kernel,opencl,scalar,Vector,Kernel,Opencl,Scalar,我正在读一篇关于使用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)) {

我正在读一篇关于使用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
#如果已定义(标量内核)
__内核空f_清除(
__全球浮动*f,
__常数(内部){

对于(unsigned i=get_global_id(0)+1;i一些设备,如AMD、ATI和Intel,非常擅长支持向量类型。这些向量是SIMD,如果可能的话,使用起来更快。NVIDIA在OpenCL中支持向量方面似乎不是很好(至少是我测试过的所有设备)


这两个循环似乎都清除了一块大小为
nall

的全局内存。一些设备,如AMD、ATI和Intel,在支持向量类型方面非常出色。这些向量是SIMD,如果可能的话,使用起来更快。NVIDIA在OpenCL中支持向量方面似乎不是很好(至少是我测试过的所有设备)


这两个循环似乎都清除了一块大小为
nall

的全局内存,标量和向量只是在OpenCL中执行相同操作的不同方式。 但是向量是一种可行的方法,因为编译器(CPU或GPU/FPGA)应该更好地优化向量。这样编译器就可以自然地开发SIMD单元。因此,如果可能且更容易,请使用它们

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

但是,查看代码是非常无效的。同一工作组中的工作项正在访问完全不同的全局内存区域,这打破了合并。只需(如您所说)执行以下操作就会更好:

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


PS:如果我必须这样做,我宁愿调用一个clEnqueueWriteBuffer并从CPU中清除内存。因为它可以与其他内核执行并行完成。

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

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

但是,查看代码是非常无效的。同一工作组中的工作项正在访问完全不同的全局内存区域,这打破了合并。只需(如您所说)执行以下操作就会更好:

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

PS:如果我必须这样做,我宁愿调用一个clEnqueueWriteBuffer并从CPU中清除内存。因为它可以与其他内核执行并行完成

__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);
}