从OpenMP循环中访问和编辑Qmap时出错

时间:2019-04-03 21:05:48

标签: c++ qt openmp qmap qvector

我正在用c ++中的openmp进行循环,以从QVector馈送QMAP内部的某些值,在某些计算机中它说“程序停止工作”,但在某些计算机中它起作用了。

我看到Qmap不是线程安全的,但是我需要一个带有标签的容器(因为我使用了Qmap)来输入内部计算的结果,并在以后的代码串行部分中使用它。

我的代码示例如下:mystringlistQStringthemapsQMap<QString, QMap<int, QVector<float>>>,而myvectorQVector<float>

#pragma omp parallel for  schedule(static) num_threads(std::thread::hardware_concurrency())
 for (int i = 0; i < numb_of_iter; i++) 
{
   for each (auto var in mystringlist)
   {
       for (int j = 0; j < 33; j++)
       {
           themaps[var][i] << std::log10(j+1) + myvector[i]; 
       }
    }
}

在串行模式下,此代码有效,但是有时在并行块中会崩溃。所以我的想法是,如果有一种方法允许所有线程访问该变量themaps,这样它就不会崩溃,因为它们不会尝试在相同的内存空间中进行写入,每个线程都有自己的i,因此它们应该能够去做。我不知道另一种选择,因为我稍后需要在代码中使用此变量themaps

1 个答案:

答案 0 :(得分:1)

明智的解决方案:通过mutex保护共享变量。您当然要为此付出性能上的损失,只有在新值的计算花费的时间比插入到数据结构中的时间长得多的情况下,这才是可接受的。

大胆的解决方案:预分配所有字段,以使数据结构不会由于插入而改变。

您需要考虑两种影响:

  1. 如果您访问的QMap键不存在,则会创建一个新字段。地图将分离。这将更改内部数据布局。
  2. 如果您使用非const方法访问该地图,则如果您对其有多个引用(Qt的写时复制习惯),该地图也会分离。

对于QVector,使用QVector::resize(n)很简单。此后,只要没有其他人可以同时读取或写入该字段,就可以在[0..n-1]内设置任何字段值。

QMap是另一种野兽。尽可能避免。
(仅提示:只有迭代器保证不返回该项目的副本。)