我有希望使用Cuda C ++处理的数据,我一次处理四个像素,这四个像素都共享一个角。例如,对于字段中的所有位置,我将一起对四个+
像素进行操作:
------------
--------++--
--------++--
------------
------------
因此,为了避免内存冲突,我决定将工作分四次运行,因为每次飞行都可以并行运行而不会与其他线程发生冲突,因为没有两个线程同时在相同的像素上工作:
// We break the threads up into four flights:
//
// 0: even X and even Y
// 1: odd X and even Y
// 2: even X and odd Y
// 3: odd X and odd Y
const int flight = ( threadIdx.x % 2 + ( ( threadIdx.y % 2 ) << 1 ) );
for (int idx = 0; idx < flight; ++idx) {
__syncthreads();
}
doWork( pixel[ threadIdx.x + threadIdx.y * blockDim.x ],
pixel[ threadIdx.x + 1 + threadIdx.y * blockDim.x ],
pixel[ threadIdx.x + 1 + (threadIdx.y + 1) * blockDim.x ],
pixel[ threadIdx.x + (threadIdx.y + 1) * blockDim.x ]);
for (int idx = 3; idx > flight; --idx) {
__syncthreads();
}
目标是将工作分解为四个同步的飞行,如下所示:
什至X /甚至Y航班:
doWork(...);
__syncthreads("one");
__syncthreads("two");
__syncthreads("three");
奇数X /偶数Y航班:
__syncthreads("one");
doWork(...);
__syncthreads("two");
__syncthreads("three");
什至X /奇Y航班:
__syncthreads("one");
__syncthreads("two");
doWork(...);
__syncthreads("three");
奇数X /奇数Y航班:
__syncthreads("one");
__syncthreads("two");
__syncthreads("three");
doWork(...);
但是,我认为__syncthreads()
不会做我想要的事情,因为我的应用程序似乎无法正常工作。
我能以某种方式标识我的同步点吗(如按名称),以便代码如上面的示例所示在成对的航班之间具有三个同步?或者在Cuda中有更好的方法可以做到这一点?
启动配置如下:
const int32_t pixelBlockSize = <argument to function>;
const int32_t pixelGridSize = <argument to function>;
const size_t scratch = (pixelBlockSize * pixelBlockSize + 2) * sizeof( float );
const dim3 dimBlock( pixelBlockSize, pixelBlockSize );
const dim3 dimGrid( pixelGridSize, pixelGridSize );
CallKernel<<< dimGrid, dimBlock, scratch >>> ( ... )
答案 0 :(得分:1)
__syncthreads()
是一个同步点。没有办法让几个单独的线程通过__syncthreads()
进行同步。每个__syncthreads()
是一个障碍,导致块中的每个所有线程等待,直到该块的所有个线程到达__syncthreads()
的地步。分支中不能包含__syncthreads()
。块必须的所有(未退出)线程都到达每个__syncthreads()
;否则,行为是不确定的。尽管在PTX级别,there would be ways进行了更细粒度的屏障同步,但我认为这些并不是真正的答案。如果我正确理解了您的问题,那么您所寻找的似乎只是
doWork(…)
__syncthreads();
doWork(…)
__syncthreads();
doWork(…)
__syncthreads();
doWork(…)
每个块的所有线程并行运行初始doWork(…)
。您要等到所有线程都完成为止。然后,您运行下一个doWork(…)
,依此类推……
通常,您可能还想看看cooperative groups library,它在基本CUDA同步原语的基础上提供了一个不错的抽象层。
答案 1 :(得分:0)
根据迈克尔·肯泽尔的答案:
// We break the threads up into four flights:
//
// 0: even X and even Y
// 1: odd X and even Y
// 2: even X and odd Y
// 3: odd X and odd Y
const int flight = ( threadIdx.x % 2 + ( ( threadIdx.y % 2 ) << 1 ) );
auto Process = [&](const bool run) {
if ( run )
{
doWork( pixel[ threadIdx.x + threadIdx.y * blockDim.x ],
pixel[ threadIdx.x + 1 + threadIdx.y * blockDim.x ],
pixel[ threadIdx.x + 1 + (threadIdx.y + 1) * blockDim.x ],
pixel[ threadIdx.x + (threadIdx.y + 1) * blockDim.x ]);
}
};
Process( 0 == flight ); __syncthreads();
Process( 1 == flight ); __syncthreads();
Process( 2 == flight ); __syncthreads();
Process( 3 == flight );