c - Fortran 的准确性和速度与 C 的对比

标签 c fortran90 gfortran

这个主题可能已被讨论过数百次。我不是要 claim 任何语言都更糟或更好。我只是想学习如何加速我的 C 代码。 所以这里有两个代码来计算 Pi。

第一个是在 Fortran90 中:

program calcpi
implicit none
integer :: i
real*8 :: pi

pi=0.0
do i = 0,1000000000
   pi = pi + 1.0/(4.0*i+1.0)
   pi = pi - 1.0/(4.0*i+3.0)
end do

pi = pi * 4.0

write(*,*) pi

end program calcpi

第二个在 C 中:

#include<stdio.h>
#define STEPCOUNTER 1000000001
int main(int argc, char * argv[])
{
long i;
double pi=0;
#pragma omp parallel for reduction(+: pi)
for ( i=0 ; i < STEPCOUNTER; i++){
   /*pi/4=1/11/3+1/51/7+...
   To avoid the need to continually change
   the sign (s=1; in each step s=s*-1 ),
   we add two elements at the same time.*/

   pi+=1.0/(i*4.0+1.0);   
   pi-=1.0/(i*4.0+3.0);   
//   pi = pi +  1.0/(i*4.0+1.0);
//   pi = pi -  1.0/(i*4.0+3.0);
}

 pi=pi*4.0;
 printf("Pi=%lf\n",pi);
return 0;
}

我正在 CentOS 6 机器上使用 gcc 4.4.4 版编译这两个代码。

[oz@centos ~]$ gfortran calcpi.f90 -o calcpi.fort.o
[oz@centos ~]$ gfortran calcpi.c -o calcpi.c.o   

CPU 是 Intel(R) Xeon(R) CPU 5160 @ 3.00GHz。

因此,这是运行每个代码所花费的时间:

[oz@centos ~]$ time ./calcpi.c.o 
Pi=3.141593

real    0m33.270s
user    0m33.261s
sys     0m0.000s
[oz@centos ~]$ time ./calcpi.fort.o 
   3.1415926553497115     

real    0m27.220s
user    0m27.208s
sys     0m0.001s

Fortran 大约快 20%。 我的问题是什么是最好的编译器标志来加速,但仍然保持稳定性和准确性?

(是的,我知道 man gcc,我想了解用户的意见)。

感谢您的意见。

结果,没有 OpenMP pragma:

[oz@centos ~]$ time ./calcpi.c.o 
Pi=3.141593

real    0m32.892s
user    0m32.885s
sys     0m0.001s

其他结果,不改变代码本身:

$ gcc -O2 calcpi.c -o calcpi.c.o
$ time ./calcpi.c.o 
Pi=3.141593

real    0m21.085s
user    0m21.078s
sys     0m0.000s
$ gfortran -O2 calcpi.c -o calcpi.c.o
$ time ./calcpi.fort.o 
   3.1415926553497115     

real    0m26.892s
user    0m26.888s
sys     0m0.000s

最佳答案

通过以 double 进行所有计算,修改 Fortran 程序,使其与 C 版本相对应:


program calcpi
  implicit none
  integer :: i
  integer, parameter :: p = selected_real_kind(15)
  real(p) :: pi

  pi=0.0_p
  do i = 0,1000000000
     pi = pi + 1.0_p/(4.0_p*i+1.0_p)
     pi = pi - 1.0_p/(4.0_p*i+3.0_p)
  end do

  pi = pi * 4.0_p

  write(*,*) pi

end program calcpi

在 Xeon X3450 (2.67 GHz) 上使用 GCC 4.4.3 在 x86_64-linux-gnu 上使用 -O2 进行编译,我得到以下计时:

$ time ./calcpi_c 
Pi=3.141593

real    0m13.903s
user    0m13.860s
sys 0m0.010s
$ time ./calcpi_fort 
   3.1415926530880767     

real    0m13.876s
user    0m13.840s
sys 0m0.000s

IOW,它们或多或少无法区分。这就是人们对这样一个简单示例的期望。

关于c - Fortran 的准确性和速度与 C 的对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8487685/

相关文章:

c++ - 从 C 程序调用 C++ DLL 时,当我尝试访问 DLL 中的调用参数指针时它崩溃了

file - FORTRAN 90 如何找出文件夹中的文件数

c - 使用 f2c 从 Fortran 翻译而来的 C 代码中出现错误

optimization - 在 forall 循环中使用用户定义的函数

fortran - 大多数编译器会优化 MATMUL(TRANSPOSE(A),B) 吗?

fortran - 作为派生类型组件的指针

c - 在 c 中使用带套接字的线程

c - 是否可以在 C 中自动生成的变量名中使用 __LINE__ ?

程序异常终止导致的 C 潜在内存泄漏

multidimensional-array - 在Fortran 90中使用2d数组与派生类型的数组