C++ 17引入了许多新算法来支持并行执行,特别是标准::减少 http://en.cppreference.com/w/cpp/algorithm/reduce是一个并行版本std::累积 http://en.cppreference.com/w/cpp/algorithm/accumulate这允许non-deterministic
的行为non-commutative
运算,例如浮点加法。我想使用 OpenCL 2 实现一个归约算法。
英特尔有一个例子here https://www.intel.com/content/dam/develop/external/us/en/documents/opencl-workgroupfunctions-531084.pdf它使用 OpenCL 2work group
内核函数来实现std::exclusive_scan http://en.cppreference.com/w/cpp/algorithm/exclusive_scanOpenCL 2 内核。下面是内核对浮点数求和,基于 Intel 的exclusive_scan
例子:
kernel void sum_float (global float* sum, global float* values)
{
float sum_val = 0.0f;
for (size_t i = 0u; i < get_num_groups(0); ++i)
{
size_t index = get_local_id(0) + i * get_enqueued_local_size(0);
float value = work_group_reduce_add(values[index]);
sum_val += work_group_broadcast(value, 0u);
}
sum[0] = sum_val;
}
上面的内核可以工作(或者看起来可以!)。然而,exclusive_scan
需要的work_group_broadcast
传递最后一个值 1 的函数work group
到下一个,而这个内核只需要将work_group_reduce_add的结果添加到sum_val
, so an atomic add
更合适。
OpenCL 2 提供了atomic_int
它支持atomic_fetch_add
。上述使用atomic_int 的内核的整数版本是:
kernel void sum_int (global int* sum, global int* values)
{
atomic_int sum_val;
atomic_init(&sum_val, 0);
for (size_t i = 0u; i < get_num_groups(0); ++i)
{
size_t index = get_local_id(0) + i * get_enqueued_local_size(0);
int value = work_group_reduce_add(values[index]);
atomic_fetch_add(&sum_val, value);
}
sum[0] = atomic_load(&sum_val);
}
OpenCL 2 还提供了atomic_float
but it doesn't支持atomic_fetch_add
.
实现 OpenCL2 内核对浮点数求和的最佳方法是什么?