Fortran 95 构造(例如 WHERE、FORALL 和 SPREAD)通常会导致更快的并行代码吗?

Posted

技术标签:

【中文标题】Fortran 95 构造(例如 WHERE、FORALL 和 SPREAD)通常会导致更快的并行代码吗?【英文标题】:Do Fortran 95 constructs such as WHERE, FORALL and SPREAD generally result in faster parallel code? 【发布时间】:2010-11-08 07:54:42 【问题描述】:

我已通读 Metcalf、Reid 和 Cohen 的 Fortran 95 书籍,以及 Fortran 90 中的数字食谱。他们建议使用 WHERE、FORALL 和 SPREAD 等方法来避免不必要的程序序列化。

但是,我偶然发现了this answer,它声称 FORALL 在理论上很好,但在实践中毫无意义 - 您最好编写循环,因为它们也可以并行化,并且您可以使用 OpenMP(或一些编译器,例如 Intel)。

任何人都可以根据经验验证他们是否普遍发现这些构造在并行性能方面比显式循环和 if 语句具有任何优势?

该语言是否还有其他一些原则上很好但在实践中不值得的并行特性?

我很欣赏这些问题的答案在某种程度上取决于实现,因此我对 gfortran、Intel CPU 和 SMP 并行性最感兴趣。

【问题讨论】:

【参考方案1】:

正如我在对另一个问题的回答中所说的那样,人们普遍认为 FORALL 在被引入该语言时并没有预期的那么有用。正如其他答案中已经解释的那样,它具有限制性要求和有限的作用,并且编译器已经非常擅长优化常规循环。编译器不断变得更好,并且功能因编译器而异。另一个线索是 Fortran 2008 再次尝试......除了向语言添加显式并行化(co-arrays,已经提到过)之外,还有“do concurrent”,一种需要限制的新循环形式,应该更好地允许编译器执行自动并行优化,但应该足够通用才能有用——请参阅ftp://ftp.nag.co.uk/sc22wg5/N1701-N1750/N1729.pdf。

在获得速度方面,我大多选择好的算法和程序,以提高可读性和可维护性。只有当程序太慢时,我才会定位瓶颈并重新编码或实现多线程(OpenMP)。 FORALL 或 WHERE 与显式 do 循环将产生有意义的速度差异的情况很少见——我会更多地关注它们如何清楚地说明程序的意图。

【讨论】:

【参考方案2】:

我对此进行了浅显的研究,遗憾地报告说,通常发现显式编写循环会导致程序比您编写的并行结构更快。即使是像A = 0 这样的简单的整个数组赋值,通常也优于do-loops。

我手头没有任何数据,如果我这样做了,那将是过时的。我真的应该把所有这些都放到一个测试套件中再试一次,编译器确实有所改进(有时它们也会变得更糟)。

我仍然使用并行构造,尤其是整个数组操作,因为它们是表达我想要实现的目标的最自然方式。我从未在 OpenMP 工作共享结构中测试过这些结构。我真的应该这样做。

【讨论】:

我没有询问整个数组操作,因为在许多情况下它们使代码更清晰,所以即使没有性能提升,我还是会使用它们。 Spread 沿数组创建一个额外维度并沿其复制数组:liv.ac.uk/HPC/htmlF90Course/HTMLF90CourseNotesnode259.html。关于性能测试,我对优化特定案例不太感兴趣,而更感兴趣的是在开始优化之前找到最佳的通用方法。【参考方案3】:

FORALL 是一个通用的屏蔽赋值语句(与 WHERE 一样)。它不是循环构造。

编译器可以使用 SIMD 指令(SSE2、SSE3 等)并行化 FORALL/WHERE,这对于获得一些低级并行化非常有用。当然,一些较差的编译器不会打扰,只是将代码序列化为循环。

OpenMP 和 MPI 在更粗粒度级别上更有用。

【讨论】:

【参考方案4】:

理论上,使用这样的赋值可以让编译器知道你想要做什么,并且应该允许它更好地优化它。在实践中,请参阅 Mark 的答案......我也认为如果代码看起来更干净,这很有用。我自己使用过几次 FORALL 之类的东西,但没有注意到与常规 DO 循环相比有任何性能变化。

至于优化,您打算使用哪种并行性?我非常不喜欢 OpenMP,但我想如果你打算使用它,你应该先测试这些结构。

【讨论】:

我过去使用过 OpenMP,并且能够为我的一些问题获得线性加速,至少在少量 CPU 上是这样。这似乎需要使用 DO 而不是 FORALL,因此使这个构造有点没用。如果您不喜欢 OpenMP,您还会使用什么其他方法来并行化循环? 嗯,我更喜欢 MPI,它的可扩展性更高,我更喜欢它,因为使用 OpenMP 让我在处理更复杂的并行任务时遇到了麻烦,比如哪些是并行区域的本地,哪些不是。对我来说,MPI 的好处是它更容易思考和实现并行例程。所以,对于我的大脑来说,OpenMP 只能用于最简单的例程。【参考方案5】:

*这应该是评论,而不是答案,但它不适合那个小盒子,所以我把它放在这里。不要反对我:-) 无论如何,继续对@steabert 对他的回答的评论。 OpenMP 和 MPI 是两个不同的东西;很少有人在两者之间做出选择,因为它更多地取决于您的架构而不是个人选择。就学习并行概念而言,我会推荐任何一天的 OpenMP。它更简单,以后可以轻松地继续过渡到 MPI。

但是,这不是我想说的。这是 - 几天后,英特尔宣布已开始支持 Co-Arrays,这是以前仅由 g95 支持的 F2008 功能。他们不打算放弃 g95,但事实仍然是英特尔的编译器更广泛地用于生产代码,所以这绝对是一个有趣的开发线。他们还在他们的 Visual Fortran 编译器中更改了一些东西(名称,首先:-)

链接后的更多信息:http://software.intel.com/en-us/articles/intel-compilers/

【讨论】:

我不同意“很少有人在两者之间做出选择,因为它更多地取决于您的架构而不是个人选择”,因为我相信 MPI 比 OpenMP 更独立于架构。对于后者,您会被共享内存架构困住。

以上是关于Fortran 95 构造(例如 WHERE、FORALL 和 SPREAD)通常会导致更快的并行代码吗?的主要内容,如果未能解决你的问题,请参考以下文章

Fortran 95 中的二进制搜索

力学 Fortran 预处理器

在fortran 90/95中产生声音/哔哔声

如何使用 xsl-fo 和 apache fop 0.95 显示固定的图像高度和宽度

fortran里的数组赋值

十三PHP框架Laravel学习笔记——构造器的 where 派生查询