我正在 Intel Broadwell XEON 或 AMD EPYC 7551、Intel TBB 和 Pagmo2 库上使用 GCC C++20 编写 C++ 多线程代码,以解决优化问题。如果我声明
concurrent_vector<double> X
并且 X
的元素被多个正在运行的线程同时修改,我相信这些操作将是线程安全的。如果我错了,请纠正我。
我真正的问题是:如果多个线程访问
X
的元素,即多个线程尝试同时修改 X
的元素,例如X.at(5)
,该操作是原子的且无锁的,还是会存在对性能产生重大影响的锁?另外,假设线程 0 修改 X.at(i)
,而线程 1 同时使用 X.at(j)
修改 i != j
。对性能有何影响?该操作是否是无锁的,即原子操作?
我是并发 C++/TBB 新手,无法使用 Google 搜索找到明确、清晰的答案。
我已经搜索了Google和TBB文档,但还没有找到上述问题的明确答案。我不确定 TBB 并发容器是否真的是原子的?
...该操作是否是无锁的,即原子操作?
不会有锁,但这并不意味着它的行为像
std::atomic
concurrent_vector 允许多个线程访问(读、写、取 相同元素的地址)。它不会序列化访问, 因此这些访问是否安全取决于数据类型。
会对性能产生什么影响...
tbb::concurrent_vector 通过不移动现有的来解决这个问题 调整大小时的存储。相反,为了成长,它创造了一个新的 存储块。通过快速恒定时间访问块 索引方案。请参阅 tbb/concurrent_vector.h 了解其具体情况 已实施。
然而,天下没有免费的午餐。并发向量索引 与 std::vector 相比,引入了额外的复杂性。因此,如果 我建议您不需要同时增长和访问向量 使用 std::向量。但是如果你确实有多个线程附加到一个 动态增长的数组,那么并发向量可能是一个很好的选择。
由于实现的原因,访问元素的性能成本是不可忽略的,这是支持同时增长和访问向量的用例所必需的。
注:引用自 https://community.intel.com/t5/Intel-oneAPI-Threading-Building/concurrent-vector-thread-safety/m-p/912060,以获取可能的英特尔员工的答案(因为他们的用户名包含_INTEL)。