【发布时间】:2019-09-01 01:40:07
【问题描述】:
我刚刚进入并行缩减的世界。我正在尝试用 Metal 来实现这一点。我已经能够使用原子类型和 atomic_fetch_* 函数成功编写一个简单的版本。
我现在正在尝试对非原子变量(一个简单的结构)做类似的事情。
定义如下:
struct Point2
{
int x;
int y;
};
使用这样的核函数:
kernel void compareX(const device Point2 *array [[ buffer(0) ]],
device Point2 *result [[ buffer(1) ]],
uint id [[ thread_position_in_grid ]],
uint tid [[ thread_index_in_threadgroup ]],
uint bid [[ threadgroup_position_in_grid ]],
uint blockDim [[ threads_per_threadgroup ]]) {
threadgroup Point2 shared_memory[THREADGROUP_SIZE];
uint i = bid * blockDim + tid;
shared_memory[tid] = array[i];
threadgroup_barrier(mem_flags::mem_threadgroup);
// reduction in shared memory
for (uint s = 1; s < blockDim; s *= 2) {
if (tid % (2 * s) == 0 && shared_memory[tid + s].x < shared_memory[tid].x) {
shared_memory[tid] = shared_memory[tid + s];
}
threadgroup_barrier(mem_flags::mem_threadgroup);
}
if (0 == tid ) {
///THIS IS NOT CORRECT
result[0] = shared_memory[0];
}
}
我首先认为内存复制到缓冲区/从缓冲区出现问题,但我已经验证到/从 CPU/GPU 与结构正常工作。然后我意识到它与跨线程组同步有关。
有很多关于 CUDA 的示例/文档,但很少有其他任何东西,而且 CUDA 并不总是能很好地转化为 Metal。
在没有原子类型的情况下,如何获得跨线程组同步?
内核正在尝试获取输入数组中的最小点。现在,由于写入顺序,结果在执行过程中会发生变化。
【问题讨论】:
-
这没有使用计算内核,因此它与您想要做的并不完全相同,但是如果您想看看基于片段着色器的方法,该方法在金属中实现前缀和,这是一个链接:github.com/mdejong/MetalPrefixSum
标签: parallel-processing gpgpu metal