20

我正在尝试使用 OpenMP 并行化 C 程序。

我想了解更多:

  1. threadprivate指令和private子句的区别和
  2. 在这种情况下,我们必须使用它们中的任何一个。

据我所知,区别在于threadprivate的全局范围和跨并行区域的保留值。我在几个示例中发现,当一段代码包含一些必须私有化的全局/静态变量时,这些变量包含在threadprivate列表中,并且它们的初始值使用copyin复制到私有副本中。

但是,是否有任何规则阻止我们使用private子句来处理全局/静态变量?也许有任何实现细节?

我在 OpenMP3.0 规范中找不到任何解释。

4

1 回答 1

26

您必须记住的最重要的区别:

  • private变量是区域的本地变量,并且大部分时间都将被放置在堆栈。变量隐私的生命周期是数据范围条款定义的持续时间。每个线程(包括主线程)都制作原始变量的私有副本(新变量不再与原始变量存储相关联)。

  • threadprivate另一方面,变量最有可能放置在堆中线程本地存储中(可以看作是线程本地的全局内存)。变量跨区域持续存在threadprivate(取决于某些限制)。主线程使用原始变量,所有其他线程制作原始变量的私有副本(主变量仍然与原始变量存储关联)。


  • 还有更棘手的区别:

    • 定义为private的变量在进入构造时为每个线程未定义,并且在退出并行构造时未定义相应的共享变量;指针的初始状态private是未定义的。

    • 但除非指定子句,threadprivate否则应假定公共块中的数据在进入第一个并行区域时未定义。copyin当一个公共块出现在threadprivate指令中时,每个线程副本在其第一次使用之前被初始化一次。

  • OpenMP 规范(第2.14.2 节)实际上对threadprivate指令给出了很好的描述(也更详细):

    变量的每个副本都threadprivate以程序指定的方式初始化一次,但在第一次引用该副本之前程序中的未指定点。根据静态变量在基础语言中的处理方式,变量的所有副本的存储都threadprivate被释放,但在程序中的未指定点。

    一个线程引用另一个线程的threadprivate变量副本的程序是不合格的。

    threadprivate如果正在执行的线程切换到另一个修改变量的任务,则变量的内容可能会在任务调度点上发生变化。有关任务调度的更多详细信息,请参阅第 14 页的第 1.3 节和第 113 页的第 2.11 节。

    parallel区域中,主线程的引用将指向遇到该parallel区域的线程中的变量副本。

    在顺序部分中,引用将指向初始线程的变量副本。保证初始线程的threadprivate变量副本中的数据值在程序中对变量的任何两个连续引用之间保持不变。

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

    • 两个parallel区域都没有嵌套在另一个显式parallel区域内。

    • 用于执行两个parallel区域的线程数相同。

    • 用于执行两个parallel区域的线程亲和性策略是相同的。

    • 封闭任务区域中的dyn-var内部控制变量的值在进入两个区域时为falseparallel

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

于 2013-08-04T16:46:23.333 回答