从 OpenMP 循环内部访问和编辑 aN ma 时出错

error acessing and editing a Qmap from inside a OpenMP loop

我正在用 c++ 中的 openmp 做一个循环,以从 QVector 在 QMAP 中提供一些值,在某些计算机中它说 "program stopped to work" 但在某些计算机中它可以工作。

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

我的代码示例如下:Being mystringlist a QString, themaps is a QMap<QString, QMap<int, QVector<float>>> and myvector a QVector<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 这样它就不会崩溃,因为它们不会尝试在同一内存中写入 space,每个线程都有自己的 i 所以它们应该能够做到这一点。我不知道这样做的另一种选择,因为稍后我需要在代码中使用此变量 themaps

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

大胆的解决方案:预分配所有字段,这样数据结构就不会因为插入而改变。

您需要考虑两个影响:

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

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

QMap 是另一种野兽。尽可能避免。
(只是一个提示:只有迭代器保证不会 return 一个 copy 项目。)