我已阅读了Metcalf,Reid和Cohen的Fortran 95书籍以及Fortran 90中的Numerical Recipes。他们建议使用WHERE,FORALL和SPREAD以避免不必要的程序序列化。
然而,我偶然发现this answer声称FORALL在理论上很好,但在实践中毫无意义 - 你也可以编写循环,因为它们也可以并行化,你可以使用OpenMP显式地并行化它们(或者自动化)一些编译器的功能,如英特尔)。
任何人都可以从经验中验证他们是否通常发现这些构造比显式循环和if并行性能方面的语句更具优势吗?
该语言还有其他任何平行的功能,但在实践中是不错的但在实践中不值得吗?
我很欣赏这些问题的答案在某种程度上依赖于实现,因此我对gfortran,Intel CPU和SMP并行性最感兴趣。
答案 0 :(得分:13)
正如我在回答另一个问题时所说的那样,人们普遍认为,FORALL在引入该语言时并没有像希望的那样有用。正如在其他答案中已经解释的那样,它具有限制性要求和有限的角色,并且编译器已经非常善于优化常规循环。编译器越来越好,编译器和编译器之间的功能各不相同。另一个线索是Fortran 2008再次尝试...除了向语言添加显式并行化(共同数组,已经提到过)之外,还有“do concurrent”,一个新的循环形式,需要限制,应该更好地允许编译器执行自动并行优化,但应该足够通用才能有用 - 请参阅ftp://ftp.nag.co.uk/sc22wg5/N1701-N1750/N1729.pdf。
在获得速度方面,我主要选择好的算法和程序以便于阅读和阅读。可维护性。只有当程序太慢时才能找到瓶颈并重新编码或实现多线程(OpenMP)。这将是一个罕见的情况,其中FORALL或WHERE与显式do循环将具有有意义的速度差异 - 我更多地看他们如何清楚地陈述程序的意图。
答案 1 :(得分:6)
我浅浅地看着这个和,可悲的报告,通常发现我的写作循环明确的结果比你写的并行结构更快的程序。甚至简单的全数组赋值(例如A = 0
)通常也优于do循环。
我手边没有任何数据,如果我这样做,那就太过分了。我真的应该将所有这些都放到测试套件中再试一次,编译器会改进(有时它们也会变得更糟)。
我仍然使用并行结构,特别是全数组操作,当它们是表达我想要实现的最自然的方式时。我还没有在OpenMP工作共享构造中测试这些构造。我真的应该。
答案 2 :(得分:2)
FORALL是一个通用的掩码赋值语句(就像WHERE一样)。它不是一个循环结构。
编译器可以使用SIMD指令(SSE2,SSE3等)并行化FORALL / WHERE,这对于获得一些低级并行化非常有用。当然,一些较差的编译器并不打扰,只是将代码序列化为循环。
OpenMP和MPI在更粗略的粒度级别上更有用。
答案 3 :(得分:0)
理论上,使用这样的赋值可以让编译器知道你想要做什么,并且应该允许它更好地优化它。在实践中,请参阅Mark的答案......我也认为如果代码看起来更干净,那么它很有用。我曾多次使用FORALL
这样的内容,但没有注意到常规DO
循环的性能变化。
至于优化,你打算使用什么样的并行主义?我非常不喜欢OpenMP,但我想如果你想使用它,你应该首先测试这些结构。
答案 4 :(得分:0)
*这应该是一个评论,而不是一个答案,但它不适合那个小盒子,所以我把它放在这里。不要反对我:-)无论如何,继续对@ steabert对他的答案的评论。 OpenMP和MPI是两回事;一个人很少在两者之间做出选择,因为它更多地取决于您的建筑而非个人选择。至于学习瘫痪的概念,我会建议任何一天的OpenMP;它更简单,后来很容易继续过渡到MPI。
但是,这不是我想说的。这是 - 从现在开始的几天,英特尔宣布它已经开始支持 Co-Arrays ,这是之前仅由g95支持的F2008功能。他们并不打算放下g95,但事实上英特尔的编译器更广泛地用于生产代码,所以这绝对是一个有趣的开发线。他们还改变了Visual Fortran编译器中的一些东西(名称,开头: - )
链接后的更多信息:http://software.intel.com/en-us/articles/intel-compilers/