并行插入到映射

Parallel insertion to map

本文关键字:映射 插入 并行      更新时间:2023-10-16

我想创建一个映射,将整数对归因为整数的向量。我的目的是以并行方式做到这一点。为了确保我不会尝试同时push_back到同一个内存实体(通过多个线程),map 键对的第二个坐标负责当前线程编号。但是,我遇到了问题。似乎某些值未正确插入。我得到的不是一起得到 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) 的不相交子序列中,这样我的代码就不会有问题......我有点困惑。有人可以向我解释这个问题吗?

如前所述,标准库容器不是线程安全的。这种情况的适当解决方案是初始化 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());

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

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

#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>()));
}
}

然后做你的平行(添加一个障碍)。