STL / OpenMP在64位版本中出现奇怪的并发问题

当我在64位调试配置中构建我们的一个项目时,我有一个奇怪的问题。它似乎产生了一些奇怪的行为,看起来有点像单个迭代器多次递增。我把它缩小到以下测试代码:
#include <omp.h>

#define _HAS_ITERATOR_DEBUGGING 0

#include <vector>
#include <set>

int main(int argc, const char* argv[]) {    
   std::vector<int> v;
   for(int j = 0; j < 20; ++j) {
      v.push_back(j);
   }

   #pragma omp parallel for
   for(int i = 0; i < 100000; ++i) {
      std::set<int> s;
      std::vector<int>::const_iterator begin = v.begin(), end = v.end();
      s.insert(begin, end); // after this line s should contain the numbers 0-19
      if(s.size() != 20) {
         printf("failn");
         exit(3);
      }
   }
   return 0;
}
但是,大小测试经常失败,这意味着它不会以某种方式插入向量的整个内容 - 并且对它进行大量的调整使得它看起来更像是向量迭代器一次增加多个步骤。这很难说,因为如果用调试器中断,它就不会发生。 绘制的明显结论是它不是线程安全的,但我的理解是它应该是因为唯一修改的变量是具有局部范围的
s
。 有很多东西可以解决眼前的问题: 删除并行 在
insert()
电话周围抛出关键部分
#define HAS_ITERATOR_DEBUGGING 1
用手动循环替换单个insert()调用并单独插入每个项目(这基本上是该函数在内部执行的操作,但是当我自己执行时问题肯定会消失) 构建相同代码的32位版本 构建相同代码的发布版本 这是在MSVC ++ 2008 SP1下编译的,带有编译器提供的STL实现。 任何人都可以了解这里发生的事情吗?提前感谢任何提示 - 我很难过:) 编辑:如果不清楚,我不是在寻找一个“快速修复”来使这个代码工作;如上所述,我知道其中很多。我想要了解的是为什么这个问题首先发生。 编辑2:使用gcc编译时代码正常工作。     
已邀请:
看起来像VS 2008实现OpenMP和/或STL中的错误。使用VS 2010,它不会被复制;此外,它不会与英特尔的编译器和VS 2008标头一起复制,这使我认为该错误更有可能在VC ++编译器的OpenMP支持中。 编辑:我之前发布的firstprivate代码确实不起作用,即使_SECURE_SCL = 1。似乎我只有一次幸运。     
我同意darhuk,我建议将
s
标为私人
#pragma omp parallel for private(s)
    
我从来没有写过任何OpenMP代码,但是我做了很多多线程编程,所以我的直觉可能是也可能不对。 集合上的insert()方法不是线程安全的,并且它失败了,因为多个线程同时调用它。您必须锁定(或某些OpenMP等效项)以确保顺序执行插入。 编辑: 试试这个
#include <omp.h>

#define _HAS_ITERATOR_DEBUGGING 0

#include <vector>
#include <set>


int main(int argc, const char* argv[]) {    
   std::vector<int> v;
   for(int j = 0; j < 20; ++j) {
      v.push_back(j);
   }


omp_lock_t writelock;
OMP_INIT_LOCK(&writelock);

   #pragma omp parallel for
   for(int i = 0; i < 100000; ++i) {
      std::set<int> s;
      std::vector<int>::const_iterator begin = v.begin(), end = v.end();
      OMP_SET_LOCK(&writelock);
      s.insert(begin, end); // after this line s should contain the numbers 0-19
      OMP_UNSET_LOCK(&writelock);
      if(s.size() != 20) {
         printf("failn");
         exit(3);
      }
   }
   return 0;
}
    

要回复问题请先登录注册