繁体   English   中英

OpenMP for C ++对象数组的循环

[英]OpenMP for loop on array of C++ objects

我正在运行一个模拟,其中生成许多随机数。 RNG实现为C ++对象,其具有返回随机数的公共方法。 为了将它与OpenMP并行化一起使用,我只需创建一个这样的RNG对象数组,每个线程一个。 然后,每个线程通过调用其中一个RNG生成自己的随机数。 例如:

  for (int i = 0; i < iTotThreads; i++) {
    aRNG[i] = new RNG();
  }
  // ... stuff here
#pragma omp parallel 
  {
    iT = omp_get_thread_num();
#pragma omp for
    for ( /* big loop */) {
      // more stuff
      aRNG[iT]->getRandomNumber();
      // more stuff
    }
  }  

即使每个RNG都在自己的成员变量上工作,并且两个这样的RNG不适合单个缓存行(我也尝试在创建时明确地对齐它们),但由于代码无法扩展,似乎存在一些错误的共享一点都不

如果我在omp并行区域内实例化对象:

#pragma omp parallel
  { 
    i = omp_get_thread_num();
    aRNG[i] = new RNG();
  }

代码完美地扩展。 你知道我在这里缺少什么吗?

编辑:顺便说一句,在第二种情况下(缩放的那个),我创建RNG的并行区域与我使用它们的并行区域不同。 我指望当我进入第二个平行区域时, aRNG[]每个指针仍然指向我的一个对象,但我想这是不好的做法......

虽然我怀疑你的描述错误共享是导致问题的原因,但为什么不以这种方式简化代码:

  // ... stuff here
#pragma omp parallel 
  {
    RNG rng;
#pragma omp for
    for ( /* big loop */) {
      // more stuff
      rng.getRandomNumber();
      // more stuff
    }
  }

parallel区域内声明rng将是具有自动存储持续时间的私有变量,因此:

  • 每个线程都有自己的私有随机数生成器(这里不允许虚假共享)
  • 您不必管理资源的分配/取消分配

如果这种方法不可行,并且遵循@HristoIliev的建议,您总是可以声明一个threadprivate变量来保存指向随机数生成器的指针:

static std::shared_pointer<RNG> rng;
#pragma omp threadprivate(rng);

并在第一个并行区域中分配它:

rng.reset( new RNG );

在这种情况下,虽然有一些注意事项可以确保跨越并行区域保留rng的值(引用OpenMP 4.0标准):

只有满足以下所有条件时,才能保证非初始线程的threadprivate变量中的数据值保持在两个连续的活动并行区域之间:

  • 并行区域都不嵌套在另一个显式并行区域内。
  • 用于执行两个并行区域的线程数相同。
  • 用于执行两个并行区域的线程亲和性策略是相同的。
  • 在进入两个并行区域时,封闭任务区域中的dyn-var内部控制变量的值为false。

如果这些条件都成立,并且如果在两个区域中引用了threadprivate变量,则在其各自区域中具有相同线程编号的线程将引用该变量的相同副本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM