将python与c/fortran进行比较

arm*_*ndo 12 c python performance fortran

我编写了以下程序来比较python与c/fortran的速度.为了获得程序使用的时间,我使用了"time"命令.所有程序计算x x + y y + z*z的平方根,其中x,y,z是浮点数.我使用了根方,因为它是科学计算中最耗时的部分之一,我参与其中.

我得到以下几次:

fortran  0m29.9s //
c        0m20.7s //
python  30m10.8s
Run Code Online (Sandbox Code Playgroud)

根据我做的简单测试,我发现Python不推荐用于科学计算.但可能我的代码效率很低.

您是否认为我可以为这个简单的测试用例提高代码效率?

Fortran语言:

program root_square
implicit none

integer i,j
real x,y,z,r

x=1.0
y=2.0
z=3.0

do j=1,3000
    do i=1,1000000
        r=sqrt(x*x+y*y+z*z)
    enddo
enddo

end program root_square
Run Code Online (Sandbox Code Playgroud)

C:

#include "stdio.h"
#include "math.h"

int main (void)
{

float x=1.0,y=2.0,z=3.0,r;
int i,j;

for(j=0; j<3000; j++){
        for(i=0; i<1000000; i++) {
                r=sqrt(x*x+y*y+z*z);
        }
}

return 0;
}
Run Code Online (Sandbox Code Playgroud)

蟒蛇:

#!/usr/bin/env python

from math import sqrt

x = 1.0
y = 2.0
z = 3.0

for j in range(1,3001):
  for i in range(1,1000001):
    r = sqrt(x*x+y*y+z*z)
Run Code Online (Sandbox Code Playgroud)

Hay*_*ach 14

我最近用更现实的真实算法进行了类似的测试.它涉及numpy,Matlab,FORTRAN和C#(通过ILNumerics).如果没有特定的优化,numpy似乎会产生比其他代码效率低得多的代码.当然 - 一如既往 - 这只能说明一般趋势.您将能够编写FORTRAN代码,最终运行速度比相应的numpy实现慢.但大多数时候,numpy会慢得多.这是我测试的(平均)结果:

kmeans比较结果

为了计算像你的例子中那样简单的浮点运算,所有这些都归结为编译器生成"最优"机器指令的能力.在这里,并不是那么重要,涉及多少个编译步骤..NET和numpy通过首先编译为比在虚拟机中执行的字节代码而使用多个步骤.但理论上,优化结果的选择同样存在.在实践中,现代FORTRAN和C编译器在优化执行速度方面更好.作为一个例子,他们利用浮点扩展(SSE,AVX)并做更好的循环展开.numpy(或更好的CPython,主要用于numpy)似乎在这一点上表现更差.如果要确保哪个框架最适合您的任务,您可以附加到调试器并调查可执行文件的最终机器指令.

但是,请记住,在更现实的情况下,浮点性能仅在大型优化链的最后才是重要的.差异往往被更强大的效果掩盖:记忆带宽.一旦开始处理数组(在大多数科学应用程序中很常见),您将不得不考虑内存管理的成本.框架在编写内存有效算法时偏向于支持算法作者.在我看来,numpy使得编写内存有效的算法比FORTRAN或C更难.但是在任何一种语言中都不容易.(ILNumerics大大改善了这一点.)

另一个重点是并行化.框架是否支持您并行执行计算?它的效率如何?我的个人观点:无论是C还是FORTRAN,还是numpy都无法轻松地并行化您的算法.但FORTRAN和C至少给你机会这样做,即使有时需要使用特殊的编译器.其他框架(ILNumerics,Matlab)自动并行化.

如果您需要非常小但成本高昂的算法的"峰值性能",那么最好使用FORTRAN或C.最好是因为它们最终会生成更好的机器代码(在单处理器系统上).然而,在写作C或FORTRAN更大的算法服用存储器效率并行性考虑往往变得繁琐.在这里,更高级别的语言(如numpy,ILNumerics或Matlab)超越了低级语言.如果做得好 - 执行速度的差异往往可以忽略不计.不幸的是,对于numpy来说,这通常是不正确的.


Mic*_*lon 5

有缺陷的基准.

如果你想计算浮点运算的时间,那么你应该第一次循环什么都不做(或者你可以管理的几乎没有).为了避免优化掉整个循环,请确保它正在执行将单个字节char从一个数组移动到另一个数组的操作.

然后使用浮点计算再次计时并减去第一个时间以获得更准确的数字.

此外,Python只有双浮点数,因此更均匀的测试将确保其他语言也使用浮点数.正如其他人所提到的,Python被广泛用于科学计算,但是那些科学家通常使用numpy库进行矩阵计算而不是编写Python循环.