我已经读过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
答案 0 :(得分:4)
分支本身并不慢。分歧是什么让你。 GPU在“warps”或“wavefronts”的锁定步骤中计算多个工作项(典型值为16或32),如果不同的工作项采用不同的路径,则它们都采用所有路径,但是根据它们所在的路径进行门写(使用谓词)标志))。因此,如果您的工作项总是(或大多数)以相同的方式分支,那么您就是好的。如果他们没有惩罚可以抢劫表现。
答案 1 :(得分:1)
如果你需要进行比较,如果数组长度'n'非常大,那么你可以使用简化而不是顺序比较。减少将在O(log n)时间内并行比较,而不是按顺序进行O(n)。
当您在GPU线程中按顺序访问内存时,内存访问是连续的,因为从同一个库访问连续的块。相反,它很好用于合并读取。你可以找到很多这方面的例子。
在GPU上,不要多次访问全局内存(因为GPU内存管理和缓存工作与CPU不完全相同)。相反,尽可能地将全局内存元素缓存到线程的私有变量/共享内存中。