我想从执行基数排序的内核内部调用一个独占扫描函数。但是独占扫描只需要一半的线程来完成它的工作。
独占扫描算法需要几个 __syncthreads() 。如果我一开始有一个声明,比如
如果(threadIdx.x > NTHREADS/2)返回;
这些线程不会参与独占扫描同步线程,这是不允许的。有没有办法解决这个问题。我确实调用了由 __syncthread()s 包围的独占扫描。
我想从执行基数排序的内核内部调用一个独占扫描函数。但是独占扫描只需要一半的线程来完成它的工作。
独占扫描算法需要几个 __syncthreads() 。如果我一开始有一个声明,比如
如果(threadIdx.x > NTHREADS/2)返回;
这些线程不会参与独占扫描同步线程,这是不允许的。有没有办法解决这个问题。我确实调用了由 __syncthread()s 包围的独占扫描。
像这样的东西应该可以工作(不要使用提前返回):
__syncthreads(); // at entry to exclusive scan region
// begin exclusive scan function
if (threadIdx.x < NTHREADS/2) {
// do first phase of exclusive scan up to first syncthreads
}
__syncthreads(); // first syncthreads in exclusive scan function
if (threadIdx.x < NTHREADS/2) {
// do second phase of exclusive scan up to second syncthreads
}
__syncthreads(); // second syncthreads in exclusive scan function
(... etc.)
__syncthreads(); // at exit from exclusive scan region
这有点乏味,但这是我所知道的遵守__syncthreads()
使用法条文的唯一方法。您也可以尝试按照您指示的方式保留代码,使不工作的线程提前返回/退出。它可能会起作用,也可能会起作用。但不能保证它适用于未来的架构或更新的工具链。
只是指出一个替代方案:
您还可以使用 的内联汇编等效项__syncthreads()
,它允许使用可选参数来表示从计算能力 2.0 开始可用的参与线程数。像这样的东西应该工作:
#define __syncthreads_active(active_threads) asm volatile("bar.sync 0, %0;" :: "r"(active_threads));
if(threadIdx.x >= NTHREADS/2) return;
int active_warps = (NTHREADS/2 + warpSize) / warpSize;
int active_threads = active_warps * warpSize; // hopefully the compiler will optimize this to a simple active_threads = (NTHREADS/2 + warpSize) & ~32
__syncthreads_active(active_threads);
// do some work...
__syncthreads_active(active_threads);
// do some more work...
__syncthreads_active(active_threads);
免责声明:写在浏览器中,完全未经测试!
不过,是否值得麻烦是另一个问题。