如果共享堆栈或数据变量,OpenMP 是不是会将它们移动到堆中?

Posted

技术标签:

【中文标题】如果共享堆栈或数据变量,OpenMP 是不是会将它们移动到堆中?【英文标题】:Does OpenMP move stack or data variables to the heap if they are shared?如果共享堆栈或数据变量,OpenMP 是否会将它们移动到堆中? 【发布时间】:2018-06-16 13:49:17 【问题描述】:

我正在观看 OpenMP 简介系列视频,演示者不断重复“堆是共享的,堆栈是私有的”。还提到数据和文本区域是共享的。然而,他给出了父线程的堆栈变量显然是共享的示例,并且他一直将这些变量称为“在堆上”。这是一个例子:

https://youtu.be/dlrbD0mMMcQ?t=2m57s

他声称变量indexcount 在“堆上”。 index不是在父线程的栈上吗? count 不是静态变量,所以不是数据区的一部分吗?在我自己的 OMP 程序中,如果我打印这些变量的地址,它们似乎分别位于堆栈和数据区域。到目前为止,这并不是他将变量称为“堆上”的唯一地方,据我所知,这些变量是共享的,但不是在堆上。我只是想确保我没有遗漏 OMP 的工作方式。

阅读规范,我能找到关于并行区域外堆栈变量“隐式共享”的最清晰的声明:

对于任务生成构造或目标构造以外的构造,如果不存在默认子句,则这些变量引用封闭上下文中存在的同名变量

OpenMP 4.5 规范第 182 页

【问题讨论】:

"heap is shared, stack is private" 指的是每个单独线程的堆栈。显然,主线程的堆栈(例如main())可以包含线程之间共享的数据。 (就我个人而言,我不明白你怎么能指望通过观看某个中年灰人在屏幕上来回摇晃的视频来学习一门技术学科:) 这是与此What resources are shared between threads?相关的上一个问题 我确实已经读过,并且很清楚线程共享的内容,尽管我用 C 和多线程标记了这个问题,但它更多的是关于 OpenMP 如何工作的问题。我同意这些视频可能不是最好的,但它们似乎是一个不错的介绍,除了将任何共享变量称为“堆变量”的问题。他对此非常一致,以至于我认为可能是因为这些视频已经有几年的历史了,可能是旧版本的 OpenMP 用于将共享变量移动到堆或其他东西。 是的,这很奇怪。你会认为发布视频的人会足够简洁,可以使用正确的措辞——但我多年来经历了足够多的蹩脚教授,知道情况并非总是如此。 (警惕互联网视频——很多时候它们不是最好的)无论是openMP pthreads等,这个概念都不会改变。每个线程都有自己的本地调用堆栈,并且线程本地的变量是私有的。几乎所有其他内容都可以共享。 @DavidC.Rankin,“在屏幕上来回摇晃的中年灰人”是来自英特尔的 Timothy "Tim" Mattson,曾任 OpenMP 架构审查委员会首席执行官,曾工作几乎每个版本的规范都在那里。我想他知道他在说什么。堆/堆栈术语不是 OpenMP 规范的一部分,纯粹用作标准定义的数据共享类的模型。 “栈是私有的”也是多线程执行正确性模型的一个中心假设。 【参考方案1】:

措辞(堆栈/堆)不准确

OpenMP 标准在其内存模型中没有引用1 堆栈或堆。所以我会用定义的实现来回答你的问题。如果堆栈变量是共享的,我认为没有理由将它们的数据移动到堆中。如果您通过查看共享变量的指针看到它们在堆栈上,我实际上会相信。

即使是 C 标准也不包含对堆栈或堆的引用。

在我看来,您不应该使用不属于标准的概念(因此取决于实施)来推断正确性。而是使用存储持续时间和范围。

我推测 Tim Mattson 使用堆栈/堆,因为它们可能更广为人知。

1 OpenMP 允许控制线程的堆栈大小,但没有进一步参考堆栈是什么。

你指出的具体例子是错误的

即使您考虑简化:

自动存储持续时间 == "stack" 已分配/动态2 存储持续时间 == "heap"

您的分析是正确的,引用适用。根据 2.15.1.1,对于具有自动存储持续时间的对象没有预先确定的数据共享规则,该对象在构造内的范围内声明。因此,它是一个具有隐式确定的数据共享属性的变量

2 令人困惑的是,C 标准使用“分配的存储持续时间”,而 C++ 和 OpenMP 使用“动态存储持续时间”。

【讨论】:

答案是在我的知识范围内,并在仔细阅读相关标准部分后。通常这应该不言而喻,但我并不声称通常比蒂姆马特森更了解。无论如何,他也是一个人,只是可能犯了一个错误。

以上是关于如果共享堆栈或数据变量,OpenMP 是不是会将它们移动到堆中?的主要内容,如果未能解决你的问题,请参考以下文章

OpenMP 子句共享与关键

OpenMP 的全局变量

openMP 并行部分中的共享变量有些奇怪

我可以使用 OpenMP 通过单个线程释放共享变量吗?

堆地址是不是共享堆栈地址?

OpenMP数据处理子句