Memory OpenCL内核随机写入全局缓冲区安全吗?

Memory OpenCL内核随机写入全局缓冲区安全吗?,memory,opencl,Memory,Opencl,我想运行一个插入指令的OpenCL内核来获得一些执行指标。更具体地说,我添加了一个隐藏的全局缓冲区,它将从主机代码中用N个零初始化。N个值中的每一个都是整数,它们代表一个不同的度量,每个内核实例将根据其执行路径以不同的方式递增 一个简单的例子: __kernel void test(__global int *a, __global int *hiddenCounter) { if (get_global_id(0) == 0) { // do stuff and the

我想运行一个插入指令的OpenCL内核来获得一些执行指标。更具体地说,我添加了一个隐藏的全局缓冲区,它将从主机代码中用N个零初始化。N个值中的每一个都是整数,它们代表一个不同的度量,每个内核实例将根据其执行路径以不同的方式递增

一个简单的例子:

__kernel void test(__global int *a, __global int *hiddenCounter) {
    if (get_global_id(0) == 0) {
        // do stuff and then increment the appropriate counter (random numbers here)
        hiddenCounter[0] += 3;
    }
    else {
        // do stuff...
        hiddenCounter[1] += 5;
    }
}
内核执行完成后,我需要主机代码聚合(简单的元素向量加法)所有
hiddenCounter
缓冲区,并打印适当的结果

我的问题是,当多个内核实例试图写入
hiddenCounter
缓冲区的同一索引时(这在我的项目中肯定会发生),是否存在争用条件。我需要强制执行某种同步吗?或者,如果使用
\uu全局
参数,并且我需要将其更改为
\uu私有
,这是不可能的吗?之后我是否能够从主机代码聚合
\u private
缓冲区

我的问题是,当多个内核实例试图写入
hiddenCounter
缓冲区的同一索引时,是否存在争用条件

答案是肯定的,你的代码将很容易受到当前编写的比赛条件的影响

我需要强制执行某种同步吗

是的,您可以为此目的使用。除了最古老的GPU之外,其他所有GPU都将支持这一点。(任何支持OpenCL 1.2或类似扩展的内容)

请注意,这将带来不小的性能开销。根据您的访问模式和频率,在
private
local
内存中收集中间结果并在内核末尾将其写入全局内存可能会更快。(在
local
的情况下,整个工作组只会为每个更新的单元格共享一个全局原子调用-您需要使用本地原子或简化算法来累积整个工作组中各个工作项的值。)

另一种选择是使用更大的全局内存缓冲区,每个工作项或组都有计数器。在这种情况下,您不需要原子来写入它们,但随后需要在主机上组合这些值。显然,这会占用更多内存,而且可能还会占用更多内存带宽——现代GPU应该缓存对小型
hiddenCounter
缓冲区的访问。因此,你需要找出/尝试在你的情况下哪一个是较小的邪恶