OpenMP 'parallel for'预先初始化

OpenMP 'parallel for' with prior initialisation

本文关键字:初始化 parallel OpenMP for      更新时间:2023-10-16

我正在尝试与OpenMP并行化for循环。通常这应该是相当简单的。但是,我需要在执行for循环之前执行线程特定的初始化。

具体来说,我有以下问题:我有一个随机数生成器,它不是线程安全的,所以我需要为每个线程创建RNG的实例。但是我想确保不是每个线程都会产生相同的随机数。

所以我尝试了以下操作:

    #pragma omp parallel
    {
        int rndseed = 42;
        #ifdef _OPENMP
            rndseed += omp_get_thread_num();
        #endif
         // initialize randon number generator
         #pragma omp for
         for (int sampleid = 0; sampleid < numsamples; ++sampleid)
         {
             // do stuff
         }
    }

如果我使用这个结构,我在运行时得到以下错误消息:

致命用户错误1002:'#pragma omp for'不正确嵌套在工作共享结构中

那么有一种方法来做线程特定的初始化吗?

谢谢

您的错误:

Fatal User Error 1002: '#pragma omp for' improperly nested in a work-sharing construct

指的是工作共享结构的非法嵌套。事实上,OpenMP 3.1标准在2.5节中给出了以下限制:

  • 每个工作共享区域必须被团队中的所有线程遇到,或者根本没有线程遇到。
  • 对于团队中的每个线程,遇到的工作共享区域和屏障区域的顺序必须相同。

从上面引用的行可以看出,在同一个并行区域内嵌套不同的工作共享结构是不一致的。

尽管非法嵌套在您的代码片段中不可见,但我认为它是由于相对于实际代码的过度简化而隐藏起来的。给你一个提示,最常见的情况是:

  • 循环工作共享构造嵌套在单个构造中(类似于这里的例子)
  • 循环工作共享构造嵌套在另一个循环构造

如果你感兴趣,在这个答案中,后一种情况讨论得更详细。

我认为这是一个设计错误。

一个并行的for循环不只是N个线程有N个核数,而是可能有N*X个线程,1 <= N*X <numsamples。>

如果你想要一个"迭代私有"变量,那么就在循环体中声明它(但是你已经知道了);但是声明一个线程私有变量在并行for循环中使用可能是不合理的。