我有一个std::map
,其密钥与thread_num相同。每个线程都写入值std::vector
。因此可以保证每个线程仅在“他的”std::vector
上运行。
示例:
#include <iostream>
#include <omp.h>
#include <map>
#include <vector>
int main(void) {
std::map<unsigned int, std::vector<unsigned int> > M;
// initialize map using first touch policy:
#pragma omp parallel for schedule(static,1)
for (int i=0; i<omp_get_num_procs(); ++i) {
#pragma omp critical
M[omp_get_thread_num()] = std::vector<unsigned int>();
}
// do some parallel operations:
#pragma omp parallel for schedule(static)
for (int i=0; i<100; ++i) {
M[omp_get_thread_num()].push_back(i);
}
// disp the content:
for (auto it_key : M) {
std::cout << "thread " << it_key.first << " : {";
for (auto it_vec : it_key.second) {
std::cout << it_vec << " ";
}
std::cout << "\b \b}" << std::endl;
}
return 0;
}
输出看起来符合要求。问题是上述代码是否合法?所以我可以得出结论,我可以并行运行std::map
,只要我能保证只有一个线程在特定密钥的辅助数据上运行?
答案 0 :(得分:5)
您的第二个循环看起来很好,因为您不是在修改地图本身,而只是修改了键下的值。 来自
http://www.cplusplus.com/reference/map/map/operator[]/
数据竞赛 访问容器,并可能进行修改。 该函数访问一个元素并返回一个可用于修改其映射值的引用。 同时访问其他元素是安全的。 如果函数插入一个新元素,则同时迭代容器中的范围是不安全的。
第一个循环可能最好不要同时进行,因为它无论如何都是最小的工作量 - 在一个线程中执行它,然后在syn_threads中执行。它现在的标准似乎并不安全,只是碰巧在你的配置上工作。
修改强>
实际上,因为在第一个循环中你没有访问其他元素而只是插入新元素,所以标准也是安全的,尽管同时执行它没有任何好处。