VS2017 中嵌套循环的 OMP

Posted

技术标签:

【中文标题】VS2017 中嵌套循环的 OMP【英文标题】:OMP for nested loops in VS2017 【发布时间】:2018-04-08 00:23:59 【问题描述】:

我是使用 OpenMP 2.0MSVC++ 2017 的新手。我正在使用一个大数据结构(引用为bigMap),因此我需要在以最佳方式迭代时分配工作负载>。我这样做的尝试是:

std::map<int, std::set<std::pair<double, double>>> bigMap;
///thousands of values are added here

int k;
int max_threads = omp_get_max_threads();
omp_set_num_threads(max_threads);
#pragma omp parallel default(none) private(k)

  #pragma omp for
  for(k = kMax; k > kMin; k--)
  
    for (auto& myPair : bigMap[k])
    
      int pthread = omp_get_thread_num();
      std::cout << "Thread " << pthread << std::endl;
      for (auto& item : myPair)
      
         #pragma omp critical
         myMap[k-1].insert(std::make_pair(item, 0));
       
    

“pthread”的输出始终为“0”,执行时间与单线程相同(因此我假设没有创建新线程)。 为什么这段代码不起作用,以及哪些 OMP 指令 / 子句 / 部分是错误的??

更新:

OMP 现在可以工作了,但是下面的代码没有按预期工作:

#pragma omp parallel for schedule(static,1)
for (int i = 0; i < map_size; ++i) 
    #pragma omp critical
    bigMap[i] = std::set<int>();

bigMap[1] =  10, 100, 1000 ;

int i;
#pragma omp parallel for schedule(static) num_threads(8)
for (i = thread_num; i < map_size; i += thread_count)

    for (auto it = bigMap[i].begin(); it != bigMap[i].end(); ++it)
    
        int elem = *it;
        bigMap[i + 1].insert(elem);
    

我希望 bigMap[1] 中的 3 个元素被插入到 bigMap 的所有条目中,相反,它们只插入一次,对于 bigMap[2],为什么??

【问题讨论】:

你在clang或gcc下试过同样的代码吗?在这一点上,我会对 MSVC 的实施非常警惕。它已经过时了,MS 对它异常守口如瓶,即使对他们来说也是如此。 std::cout 将被序列化,并且您已经通过添加关键序列化了内部循环,因此您不能期望并行加速。如果您将外部 omp 的方向颠倒过来,那么 Microsoft OpenMP 就没有理由不足(尽管自 VS2005 以来它还没有升级)。 @zzxyz,我没有这样做是因为我为此受限于 MSVC,否则我很乐意使用可用于 OMP 版本 > 3 的东西,例如任务和自定义减少。所以我必须弄清楚如何让它在 MSVC 上工作...... @tim18 我没有注意到 std::cout 会被序列化,但事实上它是,即使它只是为了验证而添加的。关于outer omp for的反转,我没明白你的意思,你的意思是如果我把它反转回来它会表现更好?谢谢 MS 有自己的库。我可能会将它用于 MS,并将最新的用于其他所有内容。 MS端的parallel_for和诸如此类的东西。也就是说,我错过了您的代码可能有问题。 【参考方案1】:

小虫子....

#pragma omp parallel for schedule(static,1)
for (int i = 0; i < map_size; ++i) 
    #pragma omp critical
    bigMap[i] = std::set<int>();

bigMap[1] =  10, 100, 1000 ;

int i;
#pragma omp parallel for schedule(static) num_threads(8)
for (i = thread_num; i < map_size; i += thread_count)

    //here you loop on bigMap[i] which is empty execpt for i==1.
    //for (auto it = bigMap[i].begin(); it != bigMap[i].end(); ++it)
    for (auto it = bigMap[1].begin(); it != bigMap[1].end(); ++it)
    
        int elem = *it;
        bigMap[i + 1].insert(elem);
    

也许你不明白静态是什么意思。

【讨论】:

以上是关于VS2017 中嵌套循环的 OMP的主要内容,如果未能解决你的问题,请参考以下文章

嵌套循环中未正确忽略内部循环的 Pragma omp parallel

嵌套并行 omp v. 2.0 性能

2017-2-24 C#基础 for循环的嵌套

慢速嵌套循环左连接,循环中索引扫描 130k 次

2017.12.07 React组件嵌套以及for循环渲染子组件

Angular2中嵌套ngFor循环的计数器