当我将一些fortran代码移植到c时,令我感到惊讶的是,使用ifort(intel fortran编译器)编译的fortran程序与使用gcc编译的c程序之间的大部分执行时间差异来自三角函数的评估函数(sin
,cos
)。这令我感到惊讶,因为我曾经相信这个answer解释的是,正弦和余弦等函数是在微处理器内部的微码中实现的。
为了更明确地发现问题,我在fortran做了一个小测试程序
program ftest
implicit none
real(8) :: x
integer :: i
x = 0d0
do i = 1, 10000000
x = cos (2d0 * x)
end do
write (*,*) x
end program ftest
在intel Q6600
处理器和3.6.9-1-ARCH x86_64 Linux
上
我得到ifort version 12.1.0
$ ifort -o ftest ftest.f90
$ time ./ftest
-0.211417093282753
real 0m0.280s
user 0m0.273s
sys 0m0.003s
与gcc version 4.7.2
同时
$ gfortran -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m2.148s
user 0m2.090s
sys 0m0.003s
这几乎是差异的10倍!我是否仍然可以相信cos
的gcc实现是微处理器实现的包装器,其方式类似于可能在intel实现中完成的?如果这是真的,瓶颈在哪里?
修改
根据评论,启用的优化应该可以提高性能。我的观点是优化不会影响库函数......这并不意味着我不会在非平凡的程序中使用它们。但是,这里有两个额外的基准测试(现在在我的家用电脑上intel core2
)
$ gfortran -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m2.993s
user 0m2.986s
sys 0m0.000s
和
$ gfortran -Ofast -march=native -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m2.967s
user 0m2.960s
sys 0m0.003s
您(评论员)想到了哪些特别的优化?在这个特定的例子中,编译器如何利用多核处理器,每个迭代都取决于前一个迭代的结果?
编辑2
Daniel Fisher和Ilmari Karonen的基准测试让我觉得这个问题可能与gcc(4.7.2)的特定版本有关,也可能与我正在使用的特定版本(Arch x86_64 Linux)有关。我的电脑。所以我使用intel core i7
,debian x86_64 Linux
和gcc version 4.4.5
ifort version 12.1.0
框上重复测试
$ gfortran -O3 -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m0.272s
user 0m0.268s
sys 0m0.004s
和
$ ifort -O3 -o ftest ftest.f90
$ time ./ftest
-0.211417093282753
real 0m0.178s
user 0m0.176s
sys 0m0.004s
对我而言,这是一个非常可接受的性能差异,这绝不会让我问这个问题。我似乎不得不在Arch Linux论坛上询问这个问题。
然而,对整个故事的解释仍然非常受欢迎。
答案 0 :(得分:15)
大多数情况是由于数学库的差异造成的。需要考虑的一些要点: