Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 提高Fortran代码性能的技巧和技巧_Performance_Fortran_Hpc - Fatal编程技术网

Performance 提高Fortran代码性能的技巧和技巧

Performance 提高Fortran代码性能的技巧和技巧,performance,fortran,hpc,Performance,Fortran,Hpc,作为我博士学位的一部分。研究方面,我正在开发大气和海洋环流的数值模型。这些涉及到PDE的数值求解系统,大约10^6个网格点,超过10^4个时间步。因此,在数十个CPU上以MPI运行时,典型的模型模拟需要几个小时到几天才能完成。当然,尽可能提高模型效率很重要,同时确保结果是字节到字节相同的 虽然我对我的Fortran编程感到非常满意,并且意识到了一些使代码更高效的技巧,但我觉得仍然有改进的空间,而这些技巧我并不知道 目前,我确保使用尽可能少的除法,并尽量不使用文字常量(我从很早就被教导这样做,例如

作为我博士学位的一部分。研究方面,我正在开发大气和海洋环流的数值模型。这些涉及到PDE的数值求解系统,大约10^6个网格点,超过10^4个时间步。因此,在数十个CPU上以MPI运行时,典型的模型模拟需要几个小时到几天才能完成。当然,尽可能提高模型效率很重要,同时确保结果是字节到字节相同的

虽然我对我的Fortran编程感到非常满意,并且意识到了一些使代码更高效的技巧,但我觉得仍然有改进的空间,而这些技巧我并不知道

目前,我确保使用尽可能少的除法,并尽量不使用文字常量(我从很早就被教导这样做,例如在实际计算中使用half=0.5而不是0.5),使用尽可能少的超越函数等

还有哪些其他性能敏感因素?目前,我想知道以下几点:

1) 数学运算的顺序重要吗?例如,如果我有:

a=1E-7 ; b=2E4 ; c=3E13
d=a*b*c
d会根据乘法的顺序以不同的效率进行计算吗?现在,这必须是特定于编译器的,但有一个直接的答案吗?我注意到d根据顺序(精度限制)得到(稍微)不同的值,但这会影响效率吗

2) 将大量(例如几十个)数组作为参数传递给子例程,而不是从子例程中的模块访问这些数组

3) Fortran 95构造(FORALL和WHERE)与DO和IF?我知道这些在90年代很重要,当时代码向量化是一件大事,但是现在现代编译器能够向量化显式DO循环,这有什么区别吗?(我在工作中使用PGI、Intel和IBM编译器)

4) 将一个数字提高到整数次方与乘法?例如:

b=a**4

我被教导在可能的情况下总是使用后者。这是否会影响效率和/或精度?(可能还依赖于编译器)

请讨论和/或添加有关提高Fortran代码效率的技巧和技巧。外面还有什么?如果您知道与此问题相关的上述每个编译器的具体操作,请将其也包括在内

补充:请注意,我本身没有任何瓶颈或性能问题。我想问的是,在操作方面是否有优化代码的一般规则


谢谢

对不起,你提到的所有技巧都只是。。。荒唐的更确切地说,它们在实践中没有任何意义。例如:

  • 用一半(=0.5)代替0.5有什么好处
  • 用于计算
    a**4
    a*a*a
    的idem<代码>(a*a)**2也将是另一种可能性。我个人的爱好是**4,因为一个好的编译器会自动选择最好的方式
对于
**
,唯一重要的一点是
a**4
a**4.
之间的区别,后者更耗费CPU时间。但如果没有实际模拟中的测量,这一点也毫无意义

事实上,你的方法是错误的。尽可能地开发代码。之后,客观地衡量代码不同部分的成本。没有测量的优化是毫无意义的

如果一个部件的CPU占用率很高,例如50%,不要忘记,仅优化该部件不能将整个代码的成本除以大于2的因子。无论如何,从最昂贵的部分(瓶颈)开始优化工作


也不要忘记,主要的改进通常来自于更好的算法。

我赞同这样的建议,即在这个时代,你学到的这些技巧是愚蠢的。编译器现在为您完成这项工作;这样的微观优化不太可能产生重大影响,而且可能不便于移植。编写清晰易懂的代码。仔细选择你的算法。有一件事可以有所作为,那就是以正确的顺序使用多维数组的索引。。。根据您的程序的数据访问模式,将一个M X N阵列重铸为N X M会有所帮助。在此之后,如果您的程序太慢,请测量CPU消耗的位置,并仅改进这些部分。经验表明,猜测常常是错误的,并且会导致无缘无故地编写更不透明的代码。如果您的程序在代码段中花费1%的时间,速度是原来的两倍,则不会有任何区别


以下是之前关于FORALL和WHERE的答案:

你对该做什么有着先验的想法,其中一些可能会有所帮助, 但最大的回报是后验分析。
(补充:换句话说,将
a*b*c
转换为不同的顺序可能会节省几个周期(我对此表示怀疑),但与此同时,你不知道你不会因为没有充分的理由花费1000个周期而变得盲目。)

无论您如何仔细地编写代码,都会有您没有预见到的加速机会。下面是我如何找到它们的。(有些人认为有争议) 执行此操作时,最好先关闭优化标志,这样代码就不会全部被置乱。 稍后您可以打开它们,让编译器完成它的工作

让它在具有足够工作负载的调试器下运行,使其运行合理的时间长度。 当它运行时,手动中断它,仔细看看它在做什么以及为什么。 这样做几次,比如10次,这样你就不会得出错误的结论

以下是您可能会发现的示例:

  • 它可能会花费大量的时间调用数学库函数,这是不必要的,因为我们使用了一些表达式
    b=a*a*a*a