3

所以,我想知道是否最好分别处理数组的实部和虚部而不是复杂的变量来提高性能。例如,

program test
   implicit none
   integer,parameter :: n = 1e8
   real(kind=8),parameter :: pi = 4.0d0*atan(1.0d0)
   complex(kind=8),parameter :: i_ = (0.0d0,1.0d0)
   double complex :: s
   real(kind=8) :: th(n),sz, t1,t2, s1,s2
   integer :: i 
   sz = 2.0d0*pi/n
   do i=1,n 
      th(i) = sz*i
   enddo
   call cpu_time(t1)
   s= sum(exp(th*i_))
   call cpu_time(t2)
   print *, t2-t1 

   call cpu_time(t1)
   s1 = sum(cos(th))
   s2 =  sum(sin(th))
   call cpu_time(t2)
   print *, t2-t1 
end program test

以及所需要的时间

   3.7041089999999999     
   2.6299830000000002     

因此,拆分计算确实需要更少的时间。这是一个非常简单的计算。但是我有一些很长的计算并且使用复杂的变量可以提高可读性并且确实需要更少的代码行。但它会牺牲我的代码的性能吗?还是总是建议分开处理实部和虚部?

4

1 回答 1

1

更好地了解编译器可以为您做什么。一般来说,现在这样做是不值得的。创建一个小脚本来研究代码的 CPU 时间。

#!/bin/bash
src=a.f90
for fcc in gfortran ifort; do
    $fcc --version
    for flag in "-O0" "-O1" "-O2" "-O3"; do
        fexe=$fcc$flag
        echo $fcc $src -o "$fcc$flag" $flag
        $fcc $src -o $fexe $flag
        echo "run $fexe ..."
        ./$fexe
    done
done

您会注意到一些 CPU 时间可能显示非常接近于 0,因为编译器足够聪明,可以丢弃您从未使用过的计算。进行更改以避免编译优化您的计算。

print *, t2-t1, s
print *, t2-t1, s1, s2

使用 ifort 的结果就在这里,除了速度,注意精度,速度是有代价的:

ifort (IFORT) 14.0.2

ifort a.f90 -o ifort-O0 -O0
run ifort-O0 ...
   3.57999900000000      (-2.319317404797516E-009,7.034712528404704E-009)
   4.07666600000000      -2.319317404797516E-009  7.034712528404704E-009
ifort a.f90 -o ifort-O1 -O1
run ifort-O1 ...
   3.30333300000000      (-2.319317404797516E-009,7.034712528404704E-009)
   3.54666700000000      -2.319317404797516E-009  7.034712528404704E-009
ifort a.f90 -o ifort-O2 -O2
run ifort-O2 ...
   3.08000000000000      (-2.319317404797516E-009,7.034712528404704E-009)
   1.13666600000000      -6.304215927066537E-009  1.737099880017717E-009
ifort a.f90 -o ifort-O3 -O3
run ifort-O3 ...
   3.08333400000000      (-2.319317404797516E-009,7.034712528404704E-009)
   1.13666600000000      -6.304215927066537E-009  1.737099880017717E-009
sum 31.999 3.496 0:35.82 99.0% 0

您可能想知道 -O1 和 -O2 标志之间发生了什么,如果检查编译的目标文件,它链接的实际内部函数已更改为:

         U cexp
         U cos
         U sin

至 :

         U __svml_cos2
         U __svml_sin2
         U cexp

svml 代表短向量数学库。可以在英特尔 IPP 库固定精度算术函数中找到速度和精度之间的一些权衡

于 2019-12-18T02:14:12.357 回答