当我将一些 fortran 代码移植到 c 时,令我惊讶的是,使用 ifort(intel fortran 编译器)编译的 fortran 程序和使用 gcc 编译的 c 程序之间的大部分执行时间差异来自对三角函数的评估(sin,cos)。这让我感到惊讶,因为我曾经相信这个答案所解释的,正弦和余弦等函数是在微处理器内部的微码中实现的。
为了更明确地发现问题,我在 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倍的差异!我是否仍然可以相信 gcc 的实现cos是微处理器实现的包装器,其方式与英特尔实现中可能完成的方式类似?如果这是真的,瓶颈在哪里?
编辑
根据评论,启用的优化应该会提高性能。我的观点是优化不会影响库函数……这并不意味着我不在非平凡的程序中使用它们。但是,这里有两个额外的基准(现在在我的家用电脑上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 论坛上询问这个问题。
但是,对整个故事的解释仍然非常受欢迎。