Performance 为什么这个OpenCL算法中的本地内存这么慢?

Performance 为什么这个OpenCL算法中的本地内存这么慢?,performance,memory,opencl,local,Performance,Memory,Opencl,Local,我正在写一些OpenCL代码。我的内核应该基于输入图像创建一个特殊的“累加器”输出。我尝试过两个概念,虽然第二个概念使用本地内存,但它们都同样慢。你能帮我找出为什么本地内存版本这么慢吗?内核的目标GPU是AMD Radeon Pro 450 // version one __kernel void find_points(__global const unsigned char* input, __global unsigned int* output) { const unsigned i



我正在写一些OpenCL代码。我的内核应该基于输入图像创建一个特殊的“累加器”输出。我尝试过两个概念,虽然第二个概念使用本地内存,但它们都同样慢。你能帮我找出为什么本地内存版本这么慢吗?内核的目标GPU是AMD Radeon Pro 450

// version one
__kernel void find_points(__global const unsigned char* input, __global unsigned int* output) {
  const unsigned int x = get_global_id(0);
  const unsigned int y = get_global_id(1);

  int ind;

  for(k = SOME_BEGINNING; k <= SOME_END; k++) {
    // some pretty wild calculation
    // ind is not linear and accesses different areas of the output
    ind = ...
    if(input[y * WIDTH + x] == 255) {
      atomic_inc(&output[ind]);
    }
  }

}

// variant two
__kernel void find_points(__global const unsigned char* input, __global unsigned int* output) {
  const unsigned int x = get_global_id(0);
  const unsigned int y = get_global_id(1);

  __local int buf[7072];
  if(y < 221 && x < 32) {
    buf[y * 32 + x] = 0;
  }
  barrier(CLK_LOCAL_MEM_FENCE);

  int ind;
  int k;

  for(k = SOME_BEGINNING; k <= SOME_END; k++) {
    // some pretty wild calculation
    // ind is not linear and access different areas of the output
    ind = ...
    if(input[y * WIDTH + x] == 255) {
      atomic_inc(&buf[ind]);
    }
  }

  barrier(CLK_LOCAL_MEM_FENCE);
  if(get_local_id(0) == get_local_size(0) - 1)
    for(k = 0; k < 7072; k++)
      output[k] = buf[k];
  }

}
//第一版
__内核无效查找点(uu全局常量无符号字符*输入,u全局无符号整数*输出){
const unsigned int x=获取全局id(0);
const unsigned int y=get_global_id(1);
int ind;

for(k=SOME_start;k本地缓冲区大小
\uu本地int buf[7072]
(28288字节)太大。我不知道AMD Radeon Pro 450的共享内存有多大,但很可能是每个计算单元32kB或64kB

32768/28288=1
65536/28288=2
意味着只能同时运行1个或最多2个波前(64个工作项),因此计算单元的占用率非常低,因此性能较差

您的目标应该是尽可能减少本地缓冲区,以便可以同时处理更多的波前

使用
CodeXL
评测您的内核-有一些工具可以向您展示所有这些。
或者,如果您不想运行探查器更好地了解情况,可以查看
CUDA占用率计算器
excel电子表格。

Local buffer size
\uu Local int buf[7072]
(282888字节)太大了。我不知道AMD Radeon Pro 450的共享内存有多大,但很可能是每个计算单元32kB或64kB

32768/28288=1
65536/28288=2
意味着只能同时运行1个或最多2个波前(64个工作项),因此计算单元的占用率非常低,因此性能较差

您的目标应该是尽可能减少本地缓冲区,以便可以同时处理更多的波前

使用
CodeXL
评测您的内核-有一些工具可以向您展示所有这些。
或者,如果您不想运行探查器来更好地了解情况,您可以查看
CUDA占用率计算器
excel电子表格。

您好,感谢您的快速回复。我有一个理解问题:如果我在OpenCL中将我的本地工作大小设置为64,而我的全局工作大小设置为128,那么我有20个工作组oups.64也是一个波前中的线程数。因此,我将有20个波前。如果我有一个由4个SIMD和16个ALU组成的计算单元,那么我每个CU最多只能解析一个波前。本地内存是每个CU,而不是每个波前。因此,即使我同时处理两个半波前,我仍然会处理一个和同一个本地缓冲区。是吗我的理解是正确的?本地缓冲区(OpenCL术语)是每个工作组,而不是每个CU。在GPU上,本地缓冲区存储在每个CU的共享内存中。我认为,如果一个CU上可以同时运行更多的工作组(受共享内存大小和寄存器数量的限制),因此,如果您的本地缓冲区为8192字节,共享内存为32768字节,那么一个CU上可能同时运行5个工作组。如果GPU上有5个CU,那么所有20个工作组都可以同时运行。这可能在架构文档中有所解释。您好,感谢您的快速回复。我有一个理解问题:如果我将OpenCL中的本地工作大小设置为64,全局工作大小设置为128,那么我有20个工作组。64也是波阵面中的线程数。因此,我将有20个波阵面。如果我有一个由4个SIMD和16个ALU组成的计算单元,那么我每个CU只能解析一个波阵面。本地内存是每个CU,而不是每个波阵面。所以即使我同时在两个半波前上工作,我仍然会在一个相同的本地缓冲区上工作。我的理解正确吗?本地缓冲区(OpenCL术语)是每个工作组,而不是每个CU。在GPU上,本地缓冲区存储在每个CU的共享内存中。我认为如果可以,更多的工作组可以在一个CU上同时运行(受共享内存大小和寄存器数量的限制),因此,如果您的本地缓冲区为8192字节,共享内存为32768字节,那么一个CU上可能同时运行5个工作组。如果GPU上有5个CU,那么所有20个工作组都可以同时运行。这可能在架构文档中有所解释。