在C ++标准中滥用std :: memory_order :: relax的示例[n4713中的algorithms.parallel.exec / 5]

HCS*_*CSF 3 c++ c++11 relaxed-atomics c++17

std::memory_order::relaxed在C ++ Standard 中滥用的示例之一:

std::atomic<int> x{0};
int a[] = {1,2};
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) {
    x.fetch_add(1, std::memory_order::relaxed);
    // spin wait for another iteration to change the value of x
    while (x.load(std::memory_order::relaxed) == 1) { } // incorrect: assumes execution order
});
Run Code Online (Sandbox Code Playgroud)

然后说,

上面的示例取决于迭代的执行顺序,并且如果两个迭代均在同一执行线程上顺序执行,则不会终止。

问题:

  1. 注释说:“不正确:假定执行顺序”。什么是“假定执行顺序”?我想念它。

  2. “以上示例取决于迭代的执行顺序”中的“迭代”指的是什么?这是否意味着while循环中的迭代?还是指迭代std::for_each

  3. 如果的迭代std::for_each由不同的线程并行执行,那么迭代/线程之一不会退出仍然不是真的吗?因为x.fetch_add(1, std::memory_order::relaxed)是原子的,所以一个线程将生成x1,另一个线程将生成x2,并且两个线程的x == 1都是不可能的。没有?

Max*_*kin 5

“不正确:假定执行顺序”。什么是“假定执行顺序”?

它假定lambda的主体是由多个线程而不是一个线程执行的。该标准宁可说它可以并行执行。

“以上示例取决于迭代的执行顺序”中的“迭代”指的是什么?

它可能是指另一个线程对lambda的执行。但是标准并不能保证有另一个线程。参见execution_policy_tag_t

parallel_policy执行策略类型用作唯一类型,以消除并行算法过载的歧义,并指示并行算法的执行可以并行化。允许在使用此策略(通常指定为std :: execution :: par)的并行算法中调用元素访问函数,无论是在调用线程中还是在库隐式创建的线程中执行,以支持并行算法执行。在同一线程中执行的任何此类调用都相对于彼此不确定地排序。