使用并行线程填充集合是否有任何危险?

时间:2017-11-29 01:00:37

标签: c++ multithreading parallel-processing openmp

我可以在C ++中使用并行线程填充std::set对象并编辑布尔向量吗?

我对并行计算相对较新,我只是学习使用OpenMP,我听过有人说只要它们是只读的,就可以在线程之间建立共享数据结构。

我的问题是,我可以使用并行方法填充一些数据结构,只要订单不重要吗?或者你不是一般做这样的事情的原因不仅仅是订单不会被保留?

以下是我要做的事情:

input: std::vector<Object> u_set // vector containing universal set

int NUM_ELEMENTS = 1000;
std::set<int> my_set(); // set to be populated
std::vector<bool> my_bools(u_set.size(), false); // vector containing set membership information (true/false)
#pragma omp parallel for
for (int i = 0; i < NUM_ELEMENTS; ++i){
    int next_el = get_next_element(); // next element from u_set
    my_set.insert(next_el);
    my_bools[next_el] = true;
}

代码基本上从通用集中选择一个元素,然后将其值添加到子集中,并在布尔向量中将其标记为子集的成员。可以并行执行此操作吗?还是被认为是不好的形式?这样的事情会更好吗?

input: std::vector<Object> u_set // vector containing universal set

int NUM_ELEMENTS = 1000;
std::set<int> my_set(); // set to be populated
std::vector<bool> my_bools(u_set.size(), false); // vector containing set membership information (true/false)

int max_threads = omp_get_max_threads();
std::vector<std::vector<int> > elements(max_threads); // vector to contain data from each thread, so not accessing the same data structure

#pragma omp parallel for
for (int i = 0; i < NUM_ELEMENTS; ++i){
    int next_el = get_next_element(); // next element from u_set
    int curr_thread = omp_get_thread_num();
    elements[curr_thread].push_back(next_el);
}

for (auto it = elements.begin(); it != elements.end(); ++it){
    for (auto jt = elements[*it].begin(); jt != elements[*it].end(); ++it){    
    my_set.insert(*jt);
    my_bools[*jt] = true;
    }
 }

这为每个线程创建一个单独的向量,然后在最后组合它们。我知道它在技术上仍然访问相同的数据结构,但在我看来,在所有数据结构中将向量分开将使其更加安全,不会混淆。

这是一个更好的方法吗?或者只是访问同一个集合并添加到算法去了吗?

1 个答案:

答案 0 :(得分:1)

当任何其他线程调用任何其他方法时,您无法调用const容器的几乎所有非std方法。 (begin()end()以及其他一些例外情况。)

所以没有。

在其他并行库中使用的一种技术是每个线程在子容器中累积更改,子容器中的更改由工作线程以类似的方式自动合并到最终结果中。对于您使用的工具,这似乎不太合理。