OpenMP:并发写入std :: map

the*_*cky 3 c++ openmp c++11

我有一个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;
}
Run Code Online (Sandbox Code Playgroud)

输出看起来符合要求.问题是上述代码是否合法?所以我可以得出结论,我可以std::map并行操作,只要我能保证只有一个线程在特定键的辅助数据上运行?

Ily*_*kiy 5

你的第二个循环看起来很好,因为你没有修改地图本身,只是在键下修改了值.从

http://www.cplusplus.com/reference/map/map/operator[]/

数据竞争 访问容器,并可能进行修改.该函数访问一个元素并返回一个可用于修改其映射值的引用.同时访问其他元素是安全的. 如果函数插入新元素,则同时迭代容器中的范围是不安全的.

第一个循环可能最好不要同时进行,因为它无论如何都是最小的工作量 - 在一个线程和之后的syn_threads中进行.它现在的方式看起来似乎不安全,只是碰巧在您的配置上工作.

编辑

实际上,因为在第一个循环中你没有访问其他元素而只是插入新元素,所以标准也是安全的,尽管同时执行它没有任何好处.

  • @ Ilya Kobelevskiy:不,省略 omp 关键时它不起作用。非并发地初始化键是绝对必要的,因为否则多个线程可能会尝试同时插入到映射中。导致未定义的行为和段错误。 (2认同)