#几种编程语言数值计算效率
测试语言:C++、Fortran、Java、Python、Octave、C#
分别使用gcc、gfortran、oracle-java8、python2、python3、octave、dotnet(其中python使用numpy库,且需要编译的语言编译时均不开-O优化)
测试的计算是求两个10,000,000的一维数组x,y欧氏距离的平方,x是1-10000000从前到后依次递增的向量,y是x的正弦值
Fortran程序:
PROGRAM MAIN
integer N
real*8,allocatable::x(:),y(:)
read(*,*) N
allocate(x(N))
allocate(y(N))
do i=1,N+1
x(i)=i-1
y(i)=sin(real(i)-1)
end do
do i=1,N+1
x(i)=(x(i)-y(i))*(x(i)-y(i))
end do
do i=2,N+1
x(1)=x(1)+x(i)
end do
write(*,*) x(1)
deallocate(x)
deallocate(y)
end
C++程序:
#include
#include
int main(){
double *x,*y;
int N;
scanf("%d",&N);
x=(double*)malloc(sizeof(double)*N);
y=(double*)malloc(sizeof(double)*N);
for(unsigned i=0;i
Java程序:
import java.util.*;
public class speedtest{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
int N=in.nextInt();
double[] x=new double[N];
double[] y=new double[N];
for(int i=0;i
Python程序:
import math
import numpy as np
N=input()
N=int(N)
x=np.zeros(N)
y=np.zeros(N)
for i in range(N):
x[i]=i
y[i]=math.sin(i)
x=x-y
sum=np.vdot(x,x)
print(sum)
C#程序:
using System;
namespace csharp
{
class Program
{
static void Main(string[] args)
{
int N;
N=Convert.ToInt32(Console.ReadLine());
double[] x=new double[N];
double[] y=new double[N];
for(int i=0;i
octave程序(.m):
N=input('');
x=zeros(1,N);
y=zeros(1,N);
for i=1:N+1;
x(1,i)=i-1;
y(1,i)=sin(i-1);
end
x=x-y;
x*x'
通过shell中的time进行计时,得到测试结果如下:
------------------------------------------------------
fortran:
3.3333338333333678E+020
real 0m0.464s
user 0m0.384s
sys 0m0.080s
------------------------------------------------------
c++:
3.3333328333334505e+20
real 0m0.615s
user 0m0.554s
sys 0m0.060s
------------------------------------------------------
java:
3.3333328333334505E20
real 0m4.295s
user 0m4.228s
sys 0m0.072s
------------------------------------------------------
python:
3.333332833333263e+20
real 0m4.593s
user 0m4.540s
sys 0m0.547s
------------------------------------------------------
python3:
3.333332833333263e+20
real 0m5.426s
user 0m5.475s
sys 0m0.387s
------------------------------------------------------
c#(.Net core):
3.33333283333345E+20
real 0m3.049s
user 0m3.577s
sys 0m0.376s
------------------------------------------------------
octave:
3.3333e+20
real 2m24.650s
user 2m24.417s
sys 0m0.432s
可以看到Fortran和C++的运行效率远高于其他语言。
而对比Fortran和C++的效率可以看到Fortran比C++略快,不过由于本身计算时间较短,而且仅测试了一次,所以会有一些随机误差影响测试结果。可以认为Fortran和C++计算效率基本不相上下。
C#(.Net core)的效率慢于Fortran、C++,快于Java、Python,而且由于刚接触.Net core不是很会用dotnet,直接使用dotnet run在项目文件里执行的启动时间消耗很多,数组维度为1000时就需要2-3s的时间,因此实际上C#(.Net core)的效率应该更高。
Java、Python2、Python3的计算时间差距不大,其中Java略快一点,同样考虑随机误差基本上Python2和Java效率相近,而Python3则比Python2略慢一些。
Octave就不说了,符号计算支持不好,计算效率又低,也就只能解解小线性方程组了。
进一步增加数组维度采用100,000,000的数组进行测试,结果为:
------------------------------------------------------
fortran:
3.3333333833325327E+023
real 0m5.936s
user 0m5.389s
sys 0m0.516s
------------------------------------------------------
c++:
3.3333332833330380e+23
real 0m5.892s
user 0m5.376s
sys 0m0.516s
------------------------------------------------------
java:
3.333333283333038E23
real 0m47.189s
user 0m46.745s
sys 0m0.436s
------------------------------------------------------
c#(.Net core):
3.33333328333304E+23
real 0m8.819s
user 0m8.375s
sys 0m0.795s
测试使用的机器内存为4G,在使用Python计算时会发生内存占用过高而死机的情况,未进行测试,octave也没有进行测试(没什么意义了)。
从测试结果来看,C++、Fortran依旧不相上下,而C#随着计算量的增加其启动时间也被掩盖,对比10,000,000的情况可以看到实际上C#效率并不比C++和Fortran差多少,量级上来说是一样的。而java的效率也没有明显不同,与剩余三个语言相比,时间高了一个量级。内存占用情况,除了Python直接死机以外,几个测试过的语言内存占用基本都是1.6G左右,其中Fortran略小,只占1.4G(理论上2个100,000,000的双精度数组应该是1.52G的内存占用,Fortran这个1.4G比较奇怪,不知道怎么优化的)。
可以看到大规模计算Fortran和C++的效率优势是其他语言无法相比的,但是语言本身学习难度和编写难度也很高。另外C#既具有Java的优势,又兼有C的效率,确实是一个很优秀的语言。
这里python的结果不知道是怎么回事,其实numpy库的效率还是很高的,因为实际上底层实现用的还是Fortran和C的库,但是不知道为什么性能上差这么多,可能操作有些问题。
使用随机数代替原来的常值,维度设置为10,000,000则发生了一个很有意思的现象,java的运行速度突然暴增,仅次于C++和Fortran,但是python的速度没有太大变化,这可能是我最近换了Java环境的原因(⊙﹏⊙)(好像java9开始虚拟机的执行效率就提高了很多)。其他语言的计算情况基本没有变化,在使用dotnet编译出可执行文件后直接执行,速度和Java相近,现在来看这Java和C#真是有点意思。话说之前准备学Java的时候教材是Java8害怕有的代码照书上写有问题,就只装了Java8,后来系统和软件源更新,自动给我把Java10装上了还自动配置了环境,今天测试才发现原来Java这么快。这系统更新Python也从3.5升到3.6了怎么就没什么惊喜呢?
------------------------------------------------------
fortran:
1666141.1059189755
real 0m0.425s
user 0m0.381s
sys 0m0.044s
------------------------------------------------------
c++:
1.6665869264373838e+06
real 0m0.353s
user 0m0.311s
sys 0m0.040s
------------------------------------------------------
java:
1666339.9341341387
real 0m0.821s
user 0m0.842s
sys 0m0.085s
------------------------------------------------------
python:
1664946.3547216023
real 0m4.103s
user 0m4.125s
sys 0m0.598s
------------------------------------------------------
python3:
1666422.8935979758
real 0m4.313s
user 0m4.345s
sys 0m0.400s
------------------------------------------------------
.netcore(c#):
1666509.75499201
real 0m3.102s
user 0m3.382s
sys 0m0.284s
纯粹做数值计算,比如计算力学、计算电磁学、数值传热学还有神经网络训练这类任务,还是Fortran、C/C++和python合适一些。因为这类任务通常对于运行性能的要求要高于开发效率,所以这类任务会花费大量的时间去开发和优化,缩短运行时间,这时Fortran和C/C++就十分合适。不过C/C++和Fortran虽然快,但是想要使用好这几种语言,除了要学习语言本身的语法特性,还需要对硬件有一定的了解,否则编写出来的程序不仅不会快,反而可能更慢。Fortran虽然速度快但是实在太古老,很多东西用起来让人觉得反人类,也不支持面向对象的特性。不过由于本身自带复数类型、数组切片和数组运算的功能,所以在数值计算领域尤其是传统数值计算领域依然有一席之地。在学校里很多祖传代码都是Fortran的,后续的维护仍然会使用Fortran,所以即便是现在仍然有很多人在使用Fortran这种上古语言。C/C++相比于Fortran速度上没有什么区别,而且拥有新时代的语言特性,教程也比Fortran更多更全面,在数值计算上用来替代Fortran还是很合适的。python本身不算快,但是python的数值库底层大多都是优化的非常好的C或者Fortran库,速度比自己写的C、Fortran代码还要快,使用也很方便。这也是这几年python能这么火的原因。
至于Java和C#纯数值计算本来也不算它们的强项。它们的优势主要还是学习和开发效率高,对图形界面的设计开发也很方便。而且Java拥有很强的跨平台能力,而C#作为微软的产品在Windows上具有天然优势,所以作为一般应用程序的开发是非常合适的。
对于那个神奇的octave,我只能说如果你一定要用matlab,而你又买不起matlab还不愿意使用未加密版,那么octave确实是一款相对合适一些的matlab的替代品。不过,如果你可以流畅开启和使用matlab,那我建议你就当作不知道有这个东西吧。