几种语言向量计算效率
测试语言: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 <cmath>
#include <cstdio>
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<N;i++) {x[i]=i;y[i]=sin(i);}
for(unsigned i=0;i<N;i++) x[i]=(x[i]-y[i])*(x[i]-y[i]);
for(unsigned i=1;i<N;i++) x[0]+=x[i];
printf("%.16e\n",x[0]);
free(x);
free(y);
return 0;
}
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<N;i=i+1){
x[i]=i;
y[i]=Math.sin(i);
}
for(int i=0;i<N;i=i+1){
x[i]=(x[i]-y[i])*(x[i]-y[i]);
}
for(int i=1;i<N;i=i+1){
x[0]=x[0]+x[i];
}
System.out.println(x[0]);
}
}
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<N;i++){
x[i]=i;
y[i]=Math.Sin(i);
}
for(int i=0;i<N;i++){
x[i]=(x[i]-y[i])*(x[i]-y[i]);
}
for(int i=1;i<N;i++){
x[0]=x[0]+x[i];
}
Console.WriteLine(x[0]);
}
}
}
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++优势于一身,简直堪称完美,奈何微软不给力,哎。