简体   繁体   English

我可以创建一个线程安全的 std::atomic <vector<int> &gt;?

[英]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是完全可以的,如果

  • you read objects你读对象
  • you write to different objects你写入不同的对象

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM