当使用在其捕获中具有初始化程序的可变 lambda 对 std::generate_n 使用并行执行时,并行访问初始化值是否线程安全?
[MCVE]
#include<vector>
#include <algorithm>
#include <execution>
int main()
{
std::vector<int> v(1000);
std::generate_n(std::execution::par, v.data(), v.size(), [i = 0]() mutable { return i++; });
return 0;
}
访问捕获的 i
是线程安全的吗?
最佳答案
首先我们来看一下generate_n的签名:
template< class ExecutionPolicy, class ForwardIt , class Size, class Generator >
ForwardIt generate_n(ExecutionPolicy&& policy, ForwardIt first, Size count, Generator g);
重要的是最后一个参数(它是您的 lambda)是按值传递的。此外,您不知道它是如何在实现中内部传递的,因此您的 lambda 可能有一些拷贝,并且每个拷贝都有自己的计数器。我想这不是本意。
有几个选项可以在实例之间共享计数器:
在 lambda 上使用 std::ref:
const auto func = [i = std::atomic<int>()]() mutable -> int { return i++; }; std::vector<int> v(1000); std::generate_n(std::execution::par, v.data(), v.size(), std::ref(func));
仿函数实例之间的共享计数器:
std::atomic<int> i = 0; std::vector<int> v(1000); std::generate_n(std::execution::par, v.data(), v.size(), [&i]() -> int { return i++; });
请注意,在这两种情况下我都使用了 std::atomic,因为您需要自己处理同步。
关于c++ - std::generate_n 的并行执行可变 lambda 生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55590503/