OpenCL:选择最佳的global_work_size值

时间:2014-12-05 14:44:02

标签: parallel-processing opencl

假设我想添加两个大小均为1亿的向量,应该如何最佳选择global_work_size

  • 必须是global_work_size=100e6还是
  • 使用尺寸为10e6 x 10e6
  • 的2D ND范围更好
  • 还有其他策略吗?

显然,我的GPU卡远不是同时有1亿个工作项,甚至是处理元素。

更具体地说,global_work_size通常应该等于要并行处理的数据的数量吗?

由于

2 个答案:

答案 0 :(得分:1)

我的情况是,您应该专注于为您的设备选择最佳工作组大小,并让每个工作项处理多个元素。使全局工作项数量等于要处理的元素数量通常更简单,但GPU的问题非常大,尤其是某些低端GPU。

我怀疑2D系列会对你有所帮助,因为你的作品本质上是一维的。

例如,使用组大小或256,其中每个工作项处理256个元素。然后,一个小组将负责65536个元素。总数为1526组,包括390656个单独的工作项目。

来自my answer to your other question的简单内核可以正常工作。 n仍然是您的元素总数。工作项ID和工作组ID都未使用。

__kernel void vecAdd(  __global double *a, __global double *b, __global double *c, const unsigned int n)
{                                           
  //Get our global thread ID and global size
  int gid = get_global_id(0);              
  int gsize = get_global_size(0);              

  //check vs n using for-loop condition
  for(int i=gid; i<n; i+= gsize){
    c[i] = a[i] + b[i];              
  }
}

下面的内核将处理每个工作组的65536个元素块。这具有共享全局读取的优点,因为它们比先前的内核更频繁地是相邻的存储器地址。您应该使用ELEMENTS_PER_GROUP以及工作组大小来查找硬件的最佳值。

#define ELEMENTS_PER_GROUP 65536 //max # of elements to be processes by a group

__kernel void vecAddLocalized(  __global double *a, __global double *b, __global double *c, const unsigned int n)
{                                           
  int wgId = get_group_id(0);
  int wgSize = get_local_size(0);
  int itemId = get_local_id(0);

  int startIndex = wgId * ELEMENTS_PER_GROUP;
  int endIndex = startIndex + ELEMENTS_PER_GROUP;
  if(endIndex > n){
    endIndex = n;
  }

  for(int i=startIndex + itemId; i<endIndex; i+= wgSize){
    c[i] = a[i] + b[i];              
  }
}

答案 1 :(得分:1)

除非我有不同的设备,我可以将工作分开,我只是将整个线性范围一次排队。 OpenCL驱动程序将连续地处理块,这些块可以比我们更有效地同时适应硬件。他们也有机会以最佳的内存访问行为来实现这一目标。

关于选择2D与1D范围,我不会将我的问题改为2D而只是为了将较小的范围排列。但是,如果您的问题本质上是二维的(例如2d图像或2d矩阵),那么以这种方式表示它是有意义的。

编辑:mfa关于在内核中循环的观点是将较大范围压缩为较小范围的非常有效的方法。如果您的内核非常短(只是几个语句),这也非常有用,因为它可以降低所有这些工作硬件线程的启动成本。