[英]Can I make a thread-safe std::atomic<vector<int>>?
I'm having a function that needs to be executed n=1000
times.我有一个需要执行
n=1000
次的函数。 This functions does a Monte Carlo style simulation and returns an int
as the result.此函数执行蒙特卡罗风格模拟并返回一个
int
作为结果。 I'd like to run nthreads=4
in parallel.我想并行运行
nthreads=4
。 Whenever a thread finishes one cycle, it should put the result in a std::vector<int>
.每当一个线程完成一个循环时,它应该将结果放入
std::vector<int>
。 Thus, after 1000 cycles, I've a vector of 1000 int
s that can be examined by statistics.因此,在 1000 个周期后,我有一个 1000 个
int
向量,可以通过统计检查。
Since a std::vector
is not thread-safe, I thought about std::mutex
(which would surely work).由于
std::vector
不是线程安全的,我想到了std::mutex
(这肯定会起作用)。
But I wonder if I can declare a vector to be atomic and thus get around mutexes?但是我想知道是否可以将向量声明为原子向量,从而绕过互斥锁? Is it possible to have a
std::atomic<std::vector<int>>
?是否有可能有一个
std::atomic<std::vector<int>>
? And can I use push_back
etc. on it?我可以在上面使用
push_back
等吗?
C++11 §29.5/1 says C++11 §29.5/1 说
There is a generic class template atomic.
有一个泛型类模板原子。 The type of the template argument T shall be trivially copyable (3.9).
模板参数 T 的类型应该是可简单复制的(3.9)。
What does trivially copyable mean?可简单复制是什么意思?
§3.9 tells §3.9 告诉
Scalar types, trivially copyable class types (Clause 9), arrays of such types, and cv-qualified versions of these types (3.9.3) are collectively called trivially copyable types.
标量类型、可简单复制的类类型(第 9 条)、此类类型的数组以及这些类型的 cv 限定版本 (3.9.3) 统称为可简单复制的类型。
For class types (of which std::vector
is):对于类类型(其中
std::vector
是):
A trivially copyable class is a class that:
一个普通的可复制类是这样一个类:
- has no non-trivial copy constructors
没有非平凡的复制构造函数
- has no non-trivial move constructors
没有非平凡的移动构造函数
- has no non-trivial copy assignment operators
没有非平凡的复制赋值运算符
- has no non-trivial move assignment operators
没有重要的移动赋值运算符
- has a trivial destructor
有一个简单的析构函数
According to this list std::vector
is not trivially copyable and so you cannot use std::atomic<std::vector<int>>
.根据此列表,
std::vector
不是可简单复制的,因此您不能使用std::atomic<std::vector<int>>
。
Since you know the size in advance and since you do not need to use methods that would require the vector be reallocated in a different location (like push_back)
.由于您事先知道大小,并且您不需要使用需要在不同位置重新分配向量的方法(如
push_back)
。 You can use std::vector<int>::resize
or the size constructor to preallocate and preconstruct the required int
s.您可以使用
std::vector<int>::resize
或 size 构造函数来预分配和预构造所需的int
。 Therefore your concurrent threads do not need to operate on the vector itself but on the elements.因此,您的并发线程不需要对向量本身进行操作,而是对元素进行操作。
If there is no access from different threads to the same element there is no race condition.如果不同线程无法访问同一元素,则不存在竞争条件。
The same goes for int k[1000]
which is trivially copyable.对于可简单复制的
int k[1000]
也是如此。 But you do not need it to be since the threads do not change the array/vector/list itself but the elements.但是您不需要它,因为线程不会更改数组/向量/列表本身而是元素。
You don't need to.你不需要。 It is totally okay to access a
std::vector
from multiple threads, if从多个线程访问
std::vector
是完全可以的,如果
So just make sure, you create a vector of size n=1000
and depending on your thread number (1 to 4) you assign elements 0-249, 250-499 etc. to your threads.因此,请确保创建一个大小为
n=1000
的向量,并根据您的线程编号(1 到 4)将元素 0-249、250-499 等分配给您的线程。
So each of your thread computes n/nthreads
elements.所以你的每个线程都计算
n/nthreads
元素。
Atomic can be instantiated with trivially copyable types.原子可以用简单的可复制类型实例化。 Vector is not such a type.
Vector 不是这样的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.