【问题标题】:Parallel insertion to map并行插入到地图
【发布时间】:2019-01-14 23:45:38
【问题描述】:

我想创建一个映射整数对的整数向量。我的目的是以并行方式进行。为了确保我不会同时尝试 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) 的不相交子序列中,因此我的代码不应该有问题...我有点困惑。有人可以向我解释这个问题吗?

【问题讨论】:

    标签: c++ multithreading openmp


    【解决方案1】:

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

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

    需要注意的是,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());
    

    【讨论】:

    • 这里,你在最后复制向量,但你可以移动它们。这种模式只是合适的解决方案之一,而不是合适的解决方案。
    • 当然,有多种方法可以解决任何问题。然而,使用互斥锁和线程安全容器并不是一个可行的解决方案,因为它们会降低性能。 (因为每个线程都必须等待每次访问,这反过来会使它比顺序实现更糟糕)。我认为这是“适当的”解决方案,因为它是多线程算法中的一种常见模式。是的,移动会更理想。
    • 预先创建向量同样有效。
    • 但是代码呢:map,vector>组合; for (int i = 0; i
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2019-12-13
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 2011-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多