【发布时间】:2017-11-29 01:00:36
【问题描述】:
我可以使用 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;
}
}
这会为每个线程创建一个单独的向量,然后在最后将它们组合起来。我知道它在技术上仍然在访问相同的数据结构,但在我看来,将向量在整个数据结构中分开会使其免受混淆的额外安全级别。
这是更好的方法吗?还是只访问同一个集合并随着算法的进行添加就可以了?
【问题讨论】:
-
简短的回答是:不。
std::set不是线程安全的。 -
只有
const成员函数可以被并发访问。见en.cppreference.com/w/cpp/container#Thread_safety -
很公平,您有什么建议可以并行化此代码吗?第二种方式安全吗?因为它没有在相同的向量上调用 push_back?
标签: c++ multithreading parallel-processing openmp