需要帮助理解OpenCL减少吗

需要帮助理解OpenCL减少吗,opencl,Opencl,我一直在读以下说明: 下面的内核应该减少一块数据,其中有一部分我根本不理解 while (global_index < length) .... global_index += get_global_size(0) while(全局索引

我一直在读以下说明:

下面的内核应该减少一块数据,其中有一部分我根本不理解

while (global_index < length) ....  global_index += get_global_size(0)
while(全局索引<长度)。。。。全局索引+=获取全局大小(0)
我认为从按顺序排列的全局存储中读取数据更明智。这意味着在k,k+1,k+2读取数据比读取k+1000,k+2000,k+3000快。这不是他们在说全局索引+=获取全局大小(0)时所做的吗

\u内核
void reduce(uu全局浮点*缓冲区,
__局部浮动*刮伤,
__常量int长度,
__全局浮点*结果){
int global_index=get_global_id(0);
浮动累加器=无穷大;
//在输入向量块上按顺序循环
while(全局_指数<长度){
浮动元素=缓冲区[全局索引];
累加器=(累加器<元件)?累加器:元件;
全局索引+=获取全局大小(0);
}
//执行并行还原
int local_index=get_local_id(0);
划痕[局部指数]=累加器;
屏障(CLK_本地_MEM_围栏);
对于(int offset=get_local_size(0)/2;
偏移量>0;
偏移量=偏移量/2){
if(局部指数<偏移量){
浮动其他=划痕[局部索引+偏移];
浮动矿=划痕[局部指数];
划痕[局部指数]=(矿山<其他)?矿山:其他;
}
屏障(CLK_本地_MEM_围栏);
}
如果(本地_索引==0){
结果[get_group_id(0)]=划痕[0];
}
}

工作项0,1,2,3,。。。将首先读取缓冲区索引0,1,2,3,。。。并行(这通常是内存访问的最佳情况),然后是1000100110021003,。。。并行等


请记住,内核代码中的每条指令都将由所有工作项“并行”执行。

AHh,这是正确的。我想一次读一个内核。回到绘图板重新设计内核:)这不意味着get_global_size应该等于同时生成的工作项的数量吗?是的,global size是“同时”计划执行的工作项的数量。输入缓冲区可能比这个大得多,while循环的目的是:用“get_global_size(0)”元素块覆盖整个缓冲区。在while的末尾,每个工作项都有一个最小值“his”数据片。。。。然后内核的第二部分在工作组内进行缩减,使用共享内存在工作组内传递值。在内核执行结束时,每个工作组将产生一个最小值。需要第二次传递才能将数据进一步减少到一个元素。然后,我应该找出我的gpu板支持多少个同时工作项,并将其设置为全局大小,并将长度设置为缓冲区中元素的数量。?有没有简单的方法来计算一台设备可以产生多少项?
__kernel
void reduce(__global float* buffer,
            __local float* scratch,
            __const int length,
            __global float* result) {

  int global_index = get_global_id(0);
  float accumulator = INFINITY;
  // Loop sequentially over chunks of input vector
  while (global_index < length) {
    float element = buffer[global_index];
    accumulator = (accumulator < element) ? accumulator : element;
    global_index += get_global_size(0);
  }

  // Perform parallel reduction
  int local_index = get_local_id(0);
  scratch[local_index] = accumulator;
  barrier(CLK_LOCAL_MEM_FENCE);
  for(int offset = get_local_size(0) / 2;
      offset > 0;
      offset = offset / 2) {
    if (local_index < offset) {
      float other = scratch[local_index + offset];
      float mine = scratch[local_index];
      scratch[local_index] = (mine < other) ? mine : other;
    }
    barrier(CLK_LOCAL_MEM_FENCE);
  }
  if (local_index == 0) {
    result[get_group_id(0)] = scratch[0];
  }
}