并行插入到地图

时间:2019-01-14 23:45:38

标签: c++ multithreading openmp

我想创建一个映射,将整数对向量赋予整数。我的目的是并行进行。为确保我不尝试同时(通过多个线程)将push_back推到同一内存实体,映射键对的第二个坐标负责当前线程号。但是,我遇到了问题。似乎某些值未正确插入。总是没有得到10个值,而是得到的总是更少(有时是9,有时是8、6等)

map<pair<int, int>, vector<int> > test;
#pragma omp parallel num_threads(8)
{
    #pragma omp for
    for (int i = 0;i < 10;i++)
    {
        test[make_pair(i % 3, omp_get_thread_num())].push_back(i);
    }
}

我也尝试过test.at(make_pair(i % 3, omp_get_thread_num())).push_back(i),但也没有用。但是,在这种情况下,执行会异常中断。

我认为#pragma omp forfor循环分布到(0,...,9)的不相交子序列中,因此我的代码应该不会有问题...我有点困惑。有人可以向我解释这个问题吗?

2 个答案:

答案 0 :(得分:1)

如上所述,标准库容器不是线程安全的。 对于这种情况,合适的解决方案是初始化n-map(每个线程一个),然后在最后加入它们。

如前所述,使用互斥锁(并确保对地图的访问安全)将是有效的解决方案,但是也会导致性能下降。每次访问该映射时,每个线程都必须等待互斥锁解锁数据。

请注意,大小为10不足以使多线程值得使用,这里使用多线程很可能会降低性能。

map<pair<int, int>, vector<int> > test[8];
#pragma omp parallel num_threads(8)
{
    #pragma omp for
    for (int i = 0;i < large_number; i++)
    {
        int thread_id = omp_get_thread_id();
        test[thread_id][make_pair(i % 3, omp_get_thread_num())].push_back(i);
    }
}
#pragma omp barrier 

map<pair<int,int>, vector<int>> combined; 
for (int i = 0; i < 8; ++i) 
    combined.insert(test[i].begin(), test[i].end());

答案 1 :(得分:0)

那是因为映射不是线程安全的(也不是向量,但是这部分没有线程)。您必须添加互斥锁,使用无锁容器或先准备地图。

在这种情况下,通过创建所有条目从一个线程开始。

#pragma omp single
for (int i = 0;i < 3;++i)
{
for (int j = 0;i < 8;++j)
{
    test.insert(make_pair(make_pair(i, j), vector<int>()));
}
}

然后并行处理(添加障碍)。