GPU上的比较和分支有多慢

时间:2014-05-03 17:41:58

标签: cuda opencl gpgpu

我已经读过GPU上的比较和分支很慢。我想知道多少。 (我对OpenCL很熟悉,但问题对于CUDA,AMP也是一般的......)

在我开始将代码移植到GPU之前,我想知道它。特别是我有兴趣在2D阵列中找到每个点的邻域中的最低值(4或9个最近邻居)。即像卷积一样的东西,但我不需要求和和乘法,而是需要比较和分支。

例如这样的代码(注意:此示例代码尚未针对GPU进行优化更具可重组性...因此,分区到工作组,缺少本地内存... ...)< / p>

for(int i=1;i<n-1;i++){ for(int j=1;j<n-1;j++){ // iterate over 2D array
     float hij  = h[i][j];
     int imin = 0,jmin = 0;
     float dh,dhmin=0;
     // find lowest neighboring element h[i+imin][j+jmin] of h[i][j]
     dh = h[i-1][j  ]-hij;  if( dh<dhmin ){  imin = -1; jmin =  0; dhmin = dh; }
     dh = h[i+1][j  ]-hij;  if( dh<dhmin ){  imin = +1; jmin =  0; dhmin = dh; }
     dh = h[i  ][j-1]-hij;  if( dh<dhmin ){  imin =  0; jmin = -1; dhmin = dh; }
     dh = h[i  ][j+1]-hij;  if( dh<dhmin ){  imin =  0; jmin = +1; dhmin = dh; }
     if( dhmin<-0.00001 ){ // if lower
       // ... Do something with hij, dhmin and save to h[i+imin][j+jmin] ...
     }
} }
  • 尽管有很多if分支,但仍然值得移植到GPU 比较呢? (即,如果每个elemet的4-5比较比CPU上相同的4-5比较慢10倍,则会成为瓶颈)
  • 是否有任何优化技巧如何缩小if 分支和比较减慢了吗?

我在这个水力腐蚀代码中使用的: http://www.openprocessing.org/sketch/146982

2 个答案:

答案 0 :(得分:4)

分支本身并不慢。分歧是什么让你。 GPU在“warps”或“wavefronts”的锁定步骤中计算多个工作项(典型值为16或32),如果不同的工作项采用不同的路径,则它们都采用所有路径,但是根据它们所在的路径进行门写(使用谓词)标志))。因此,如果您的工作项总是(或大多数)以相同的方式分支,那么您就是好的。如果他们没有惩罚可以抢劫表现。

答案 1 :(得分:1)

如果你需要进行比较,如果数组长度'n'非常大,那么你可以使用简化而不是顺序比较。减少将在O(log n)时间内并行比较,而不是按顺序进行O(n)。

当您在GPU线程中按顺序访问内存时,内存访问是连续的,因为从同一个库访问连续的块。相反,它很好用于合并读取。你可以找到很多这方面的例子。

在GPU上,不要多次访问全局内存(因为GPU内存管理和缓存工作与CPU不完全相同)。相反,尽可能地将全局内存元素缓存到线程的私有变量/共享内存中。