matlab2019支持python_全方位对比:Python、Julia、MATLAB、IDL 和 Java (2019 版)

引言

我们使用简单的测试用例来对各种高级编程语言进行比较。我们是从新手程序员的角度来实现测试用例,假设这个新手程序员不熟悉语言中可用的优化技术。我们的目的是突出每一种语言的优缺点,而不是宣称一种语言比其他语言更优越。计时结果以秒为单位,精确到四位数,任何小于 0.0001 的值将被视为 0 秒。

本文提供的测试是在 Intel Xeon Haswell 处理器节点上进行的,每个节点有 28 核(每核 2.6GHz)和 128GB 的可用内存。Python、Java 和 Scala 测试运行在一台 Mac 计算上,该计算机配备了 Intel i7-7700HQ(4 核,每核 2.8GHz),16GB 可用内存,以便与 Xeon 节点进行比较。我们考虑这些语言使用如下版本:

语言版本号是否开源0.6.2是

10.0.2是

2.13.0是

8.5否

R3.6.1是

R2017b否

GNU 和 Intel 编译器用于 C 和 Fortran。包含这些语言是为了作为基准,这就是为什么它们的测试也带有优化版本(-O3、-Ofast)的原因。

测试用例分为四类:

循环和向量化

字符串操作

数值计算

输入 / 输出

每个测试都足够“简单”,可以用任何一种语言快速编写,旨在解决以下问题:

非连续内存位置的访问

递归函数的使用

循环或向量化的利用

海量文件的打开

任意长度的字符串的操作

矩阵的乘积

迭代求解的使用

等等

源文件包含在以下目录中:复制代码

C Fortran IDL Java Julia Matlab Python R Scala

还有一个目录:复制代码

Data

它包含一个 Python 脚本,该脚本在读取大量文件时生成测试用例所需的 NetCDF4 文件。它还有用于“计算文件中唯一单词”测试用例的示例文本文件。

备注:在下面显示的结果中,我们使用了较旧版本的 Julia,因为在 Xeon Haswell 节点上安装最新版本的 Julia(1.1.1) 时我们遇到了困难。此外,Python 实验并不包括 Numba,因为我们有权访问的 Haswell 节点使用的是较旧版本的操作系统,妨碍了 Numba 的正确安装。

循环与向量化

复制多维数组

给定任意 n x n x 3 矩阵 A,我们将执行以下操作:复制代码

A(i, j, 1) = A(i, j, 2)A(i, j, 3) = A(i, j, 1)A(i, j, 2) = A(i, j, 3)

循环和向量化的使用。该测试用例旨在测量语言访问连续内存位置的速度,并查看每种语言如何处理循环和向量化。

表 CPA-1.0:在 Xeon 节点上使用循环复制矩阵元素所用的时间。

语言选项n=5000n=7000n=9000Python16.216431.786752.5485

Julia0.07220.14450.2359

Java0.18100.32300.5390

Scala0.27500.48100.7320

IDL6.466111.906819.4499

R22.951044.976074.3480

Matlab0.28490.52030.8461

Fortrangfortran0.17600.34800.5720

gfortran -O30.06800.17200.2240

ifort0.06800.13600.2240

ifort -O30.06800.13600.2800

Cgcc0.17000.34000.5600

gcc -Ofast0.09000.18000.3100

icc0.10000.18000.3000

icc -Ofast0.10000.18000.3000

表 CPA-1.1:在 i7 Mac 上使用循环复制矩阵元素所用的时间。

语言n=5000n=7000n=9000Python18.667536.404660.2338

Python (Numba)0.33980.30600.3693

Java0.12600.24200.4190

Scala0.20400.34500.5150

表 CPA-2.0:在 Xeon 节点上使用向量化复制矩阵元素所用的时间。

语言选项n=5000n=7000n=9000Python0.49560.97391.6078

Julia0.31730.55750.9191

IDL0.39000.76411.2643

R3.52906.935011.4400

Matlab0.28620.55910.9188

Fortrangfortran0.09600.25200.3240

gfortran -O30.09600.24400.3120

ifort0.14000.22800.3840

ifort -O30.12000.23600.4560

表 CPA-2.1:在 i7 Mac 上使用向量化复制矩阵元素所用的时间。

语言n=5000n=7000n=9000Python0.56021.08321.8077

Python (Numba)0.85071.36502.0739

字符串操作

外观数列

外观数列(Look and Say Sequence)读取一个整数。在后续的每个项中,前一个项中每个整数出现的次数连接到该整数的前面。如,一个项 1223,接下来将会是 112213 ,或“一个 1,两个 2,一个 3”。这里,我们从数字开始: 1223334444 ,并确定 n 项(随 n 不同)的外观数列,这个测试用例突出显示了语言如何操作操纵任意长度的字符串。

表 LKS-1.0:在 Xeon 节点上查找 n 项的外观数列所用的时间。

语言选项n=40n=45n=48Python2.089044.4155251.1905

Java0.06940.08990.1211

Scala0.04700.12700.2170

IDL20.2926304.50491612.4277

Matlab423.22416292.7255exceeded time limit

Fortrangfortran0.00800.01200.0120

gfortran -O30.00800.01200.0120

ifort0.00400.01600.0120

ifort -O30.00800.00400.0080

Cgcc0.06000.19000.4300

gcc -Ofast0.04000.18000.4000

icc0.06000.19000.4100

icc -Ofast0.05000.19000.4100

表 LKS-1.1:在 i7 Mac 上查找 n 项的外观数列所用的时间。

语言n=40n=45n=48Python1.733122.3870126.0252

Java0.06650.09120.1543

Scala0.04900.09700.2040

文件中的唯一单词

我们打开一个任意文件,并计算其中唯一单词的数量,假设单词如下:复制代码

ab Ab aB a&*(-b: 17;A#~!b

数量是相同的(在这样的情况下,大小写、特殊字符和数字将被忽略)。在我们的测试中,使用了四个文件:复制代码

world192.txt、plrabn12.txt、bible.txt、book1.txt

表 UQW-1.0:在 Xeon 节点上计算文件中的唯一单词所用的时间。

语言world192.txt(19626 个单词)plrabn12.txt(9408 个单词)bible.txt(12605 个单词)book1.txt(12427 个单词)Python (dictionary method)0.50020.10900.88690.1850

Python (set method)0.38140.08730.75480.1458

Julia0.21900.03540.32390.0615

Java0.56240.22991.01350.2901

Scala0.46000.21500.69300.2190

R104.58208.644033.821017.6720

Matlab3.02700.96576.03481.0390

表 UQW-1.1:在 i7 Mac 上计算文件中唯一单词所用的时间。

语言world192.txt(19626 个单词)plrabn12.txt(9408 个单词)bible.txt(12605 个单词)book1.txt(12427 个单词)Python (dictionary method)0.35410.08660.73460.1448

Python (set method)0.36850.08200.71970.1417

Java0.51290.25300.91830.3220

Scala0.58100.15400.66500.2330

数值计算

斐波那契数列

斐波那契数列是一个数字序列,其中每个连续的数字是它前面两个数字的和:

b563a00e3e031ee49268aef0c46bf686.png

它的第一项是:

b563a00e3e031ee49268aef0c46bf686.png

斐波那契数列在经济学、计算机科学、生物学、组合学等领域都有广泛的应用。我们在计算第 n 个斐波那契数列时测量所用的时间。迭代计算和递归计算都需要计算时间。

表 FBC-1.0:在 Xeon 节点上迭代查找斐波那契数列所用的时间。

语言选项n=25n=35n=45Python000

Julia000

Java000

Scala000

IDL000

R0.03300.03200.0320

Matlab0.00260.00340.0038

Fortrangfortran000

gfortran -O3000

ifort000

ifort -O3000

Cgcc000

gcc -Ofast000

icc000

icc -Ofast000

表 FBC-1.1:在 i7 Mac 上迭代查找斐波那契数列所用的时间。

语言n=25n=35n=45Python000

Python (Numba)0.11000.10950.1099

Java000

Scala000

表 FBC-2.0:在 Xeon 节点上递归查找斐波那契数列所用的时间。

语言选项n=25n=35n=45Python0.05937.0291847.9716

Julia0.00030.03083.787

Java0.00110.04104.8192

Scala0.00100.05605.1400

IDL0.02382.5692304.2198

R0.00900.01000.0100

Matlab0.01421.2631149.9634

Fortrangfortran00.084010.4327

gfortran -O3000

ifort000

ifort -O3000

Cgcc00.04005.0600

gcc -Ofast00.02002.2000

icc00.03003.1400

icc -Ofast00.02003.2800

表 FBC-2.1:在 i7 Mac 上递归查找斐波那契数列所用的时间。

语言n=25n=35n=45Python0.05196.4022800.0381

Python (Numba)0.417243.76045951.6544

Java0.00300.04425.0130

Scala0.00100.04705.7720

矩阵乘法

将两个随机生成的 n x n 矩阵 A 和 B 相乘。测量执行乘法的时间。这个问题说明了利用每种语言中可用的内置库的重要性。

表 MXM-1.0:在 Xeon 节点上进行矩阵相乘所用的时间。

语言选项n=1500n=1750n=2000Pythonintrinsic0.15600.24300.3457

Juliaintrinsic0.14970.23980.3507

Javaloop13.861017.860032.3370

Scalaloop9.838019.145032.1310

Rintrinsic0.16000.24600.3620

Matlabintrinsic1.36721.39510.4917

IDLintrinsic0.18940.23090.3258

Fortrangfortran (loop)17.437131.466062.1079

gfortran -O3 (loop)3.32825.300312.1648

gfortran (matmul)0.38400.61600.9241

gfortran -O3 (matmul)0.38800.61600.9161

ifort (loop)1.14011.81612.9282

ifort -O3 (loop)1.14811.80812.9802

ifort (matmul)1.14411.81212.9242

ifort -O3 (matmul)0.51600.82811.2441

ifort (DGEMM)0.21600.23600.3320

Cgcc (loop)13.200020.980031.4400

gcc -Ofast (loop)1.45002.36004.0400

icc (loop)1.23002.15004.0500

icc -Ofast (loop)1.15001.75002.5900

表 MXM-1.1:在 i7 Mac 上进行矩阵相乘所用的时间。

语言选项n=1500n=1750n=2000Pythonintrinsic0.09060.11040.1611

Numba (loop)9.259520.201235.3174

Javaloop32.508047.768082.2810

Scalaloop23.054038.911060.3180

置信传播算法

置信传播是一种用于推理的算法,通常用于人工智能、语音识别、计算机视觉、图像处理、医学诊断、奇偶校验码等领域。我们用 5000×5000 元素矩阵来测量算法进行 n 次迭代所用的时间。在 Justin Domke 的博客(Domke 2012)中展示了 MATLAB、C 和 Julia 的代码,该博客指出,这个算法是“矩阵乘法的重复序列,然后进行归一化”。

表 BFP-1.0:在 Xeon 节点上执行置信传播算法所用的时间。

语言选项n=250n=500n=1000Python3.70767.082413.8950

Julia4.02807.822015.1210

Java63.9240123.3840246.5820

Scala53.5170106.4950212.3550

IDL16.960933.208665.7071

R23.415045.416089.7680

Matlab1.97603.80877.4036

Fortrangfortran21.001341.010687.6815

gfortran -O34.49238.256517.5731

ifort4.73639.108617.8651

ifort -O34.73639.108621.1973

Cgcc2.64005.290010.5800

gcc -Ofast2.42004.85009.7100

icc2.16004.32008.6500

icc -Ofast2.18004.34008.7100

表 BFP-1.1:在 i7 Mac 上执行置信传播算法所用的时间。

语言n=250n=500n=1000Python2.41214.54228.7730

Java55.3400107.7890214.7900

Scala47.956095.3040189.8340

梅特罗波利斯 – 黑斯廷斯(Metropolis-Hastings)算法

梅特罗波利斯 – 黑斯廷斯算法是一种用于从概率分布中提取随机样本的算法。该实现使用二维分布(Domke 2012),并测量迭代 n 次所用的时间。

表 MTH-1.0:在 Xeon 节点上执行梅特罗波利斯 – 黑斯廷斯算法所用的时间。

语言选项n=5000n=10000n=15000Python0.04040.08050.1195

Julia0.00020.00040.0006

Java0.00400.00500.0060

Scala0.00800.00900.0100

IDL0.01340.01050.0157

R0.07600.15000.2230

Matlab0.01830.02110.0263

Fortrangfortran000

gfortran -O3000

ifort0.004000

ifort -O30.00400.00400

Cgcc000

gcc -Ofast000

icc000

icc -Ofast000

表 MTH-1.1:在 i7 Mac 上执行梅特罗波利斯 – 黑斯廷斯算法所用的时间。

语言n=5000n=10000n=15000Python0.03460.06380.0989

Java0.00600.00400.0060

Scala0.00900.01000.0130

快速傅里叶变换

我们创建一个 n x n 矩阵 M ,其中包含随机复值。我们计算了 M 的快速傅里叶变换和结果的绝对值。快速傅里叶变换算法广泛用于各种科学和工程领域的信号处理和图像处理。

表 FFT-1.0:在 Xeon 节点上计算快速傅里叶变换所用的时间。

语言选项n=10000n=15000n=20000Pythonintrinsic8.079719.635734.7400

Juliaintrinsic3.97911.49020.751

IDLintrinsic16.669938.985770.8142

Rintrinsic58.2550150.1260261.5460

Matlabintrinsic2.62436.001010.66232

表 FFT-1.1:在 i7 Mac 上计算快速傅里叶变换所用的时间。

语言选项n=10000n=15000n=20000Pythonintrinsic7.953821.535555.9375

迭代求解器

我们使用雅克比法迭代求解器(Jacobi iterative solver)数值逼近二维拉布拉斯方程(Laplace equation)的解,该解用四阶紧致格式离散(Gupta,1984)。随着网络点数量的变化,我们记录所用的时间。

表 ITS-1.0:在 Xeon 节点上迭代计算近似解所用的时间。

语言选项n=100n=150n=200Python158.2056786.34252437.8560

Julia1.03085.187016.1651

Java0.41301.89505.2220

Scala0.5402.10305.7380

IDL73.2353364.13291127.1094

R157.1490774.70802414.1030

Matlab2.81635.05438.6276

Fortrangfortran0.82403.732010.7290

gfortran -O30.66803.07208.8930

ifort0.54002.47207.1560

ifort -O30.54002.46807.1560

Cgcc0.50002.42007.7200

gcc -Ofast0.22001.05003.1900

icc0.46002.23006.7800

icc -Ofast0.33001.60004.8700

表 ITS-1.2:在 i7 Mac 上迭代计算近似解所用的时间。

语言n=100n=150n=200Python174.7663865.12032666.3496

Python (Numba)1.32265.032415.1793

Java0.46001.76904.7530

Scala0.59702.09505.2830

表 ITS-2.0:在 Xeon 节点上使用向量化计算近似解所用的时间。

语言选项n=100n=150n=200Python2.627214.650540.2124

Julia2.458313.191841.0302

IDL1.711928.684128.0683

R25.2150121.9870340.4990

Matlab3.32917.648615.9766

Fortrangfortran0.86804.204011.5410

gfortran -O30.36001.80405.0880

ifort0.28001.53604.4560

ifort -O30.28001.56004.4160

表 ITS-2.1:在 i7 Mac 上使用向量化计算近似解所用的时间。

语言n=100n=150n=200Python1.70517.457222.0945

Python (Numba)2.44518.509421.7833

矩阵的平方根

给定 n x n 矩阵 A,我们寻找这样的矩阵 B,使得:

B * B = A

B 就是平方根。在我们的计算中,我们考虑对角线上为 6,别处为 1 的矩阵 A。

表 SQM-1.0:在 Xeon 节点上计算矩阵的平方根所用的时间。

语言n=1000n=2000n=4000Python1.01015.237644.4574

Julia0.42072.508019.0140

R0.56503.066019.2660

Matlab0.35711.65522.6250

表 SQM-1.1:在 i7 Mac 上计算矩阵的平方根所用的时间。

语言n=1000n=2000n=4000Python0.56533.396325.9180

高斯求积

高斯求积(Gauss-Legendre Quadrature)是逼近定积分的一种数值方法。它使用被积函数的 n 个值的加权和。如果被积函数是 0 到 2 n – 1 次多项式,则结果是精确的。这里我们考虑区间 [-3, 3] 上的指数函数,并记录当 n 变化时执行积分所用的时间。

表 GLQ-1.0:在 Xeon 节点上计算积分近似值所用的时间。

语言选项n=50n=75n=100Python0.00790.00950.0098

Julia0.00020.00040.0007

IDL0.00430.00090.0014

R0.02600.02400.0250

Matlab0.74760.07310.4982

Fortrangfortran00.00400.0080

gfortran -O300.01200.0120

ifort0.00800.00800.0080

ifort -O30.00800.00400.0080

表 GLQ-1.1:在 i7 Mac 上计算积分近似值所用的时间。

语言n=50n=75n=100Python0.01400.00350.0077

三角函数

我们在 n 元素值列表上迭代计算三角函数,然后在同一列表上计算反三角函数。当 n 发生变化时,测量完整全部操作所用的时间。

表 TRG-1.0:在 Xeon 节点上计算三角函数所用的时间。

语言选项n=80000n=90000n=100000Python14.689116.508423.6273

Julia55.392062.949069.2560

IDL37.441341.969535.2387

R91.5250102.8720113.8600

Matlab5.27945.86496.3699

Scala357.3730401.8960446.7080

Java689.6560774.9110865.057

Fortrangfortran53.483360.031766.6921

gfortran -O349.927156.023562.1678

ifort18.641120.957323.2654

ifort -O318.645120.957323.2694

Cgcc107.4400120.7300134.0900

gcc -Ofast93.0400104.5700116.0600

icc76.260085.790095.3100

icc -Ofast48.840054.960061.0600

表 TRG-1.1:在 i7 Mac 上计算三角函数所用的时间。

语言n=80000n=90000n=100000Python3.53996.19846.9207

Munchausen 数

Munchausen 数 是一个自然数,等于其自身幂次的位数之和。在以 10 为基数的情况下,有 4 个这样的数字:0、1、3435 和 438579088。我们来确定找到这些数字需要多久。

表 MCH-1.0:在 Xeon 节点上查找 Munchausen 数所用的时间。

语言选项所用时间Python1130.6220

Julia102.7760

Java4.9008

Scala72.9170

Rexceeded time limit

IDLexceeded time limit

Matlab373.9109

Fortrangfortran39.7545

gfortran -O321.3933

ifort29.6458

ifort -O329.52184

Cgcc157.3500

gcc -Ofast126.7900

icc228.2300

icc -Ofast228.1900

表 MCH-1.1:在 i7 Mac 上查找 Munchausen 数所用的时间。

语言所用时间Python1013.5649

Java4.7434

Scala64.1800

输入 / 输出

读取大量文件

我们有一套涵盖 20 年的每日 NetCDF 文件(7305)。给定年份的文件位于一个标记为 YYYY 的子目录中(例如,Y1990、Y1991、Y1992 等)。我们希望编写一个脚本,打开每个文件,读取一个三维变量(经度 / 维度 / 级别)并对其进行操作。脚本的伪代码如下:复制代码

Loop over the years Obtain the list of NetCDF files Loop over the files Read the variable (longitude/latitude/level) Compute the zonal mean average (new array of latitude/level) Extract the column array at latitude 86 degree South Append the column array to a "master" array (or matrix)

目标是能够生成三维数组(年份 / 级别 / 值)并执行等高线图。这是我们支持的典型用户面临的问题类型:需要对数千个文件进行操作以提取所需信息的集合。拥有能够从文件中快速读取数据(如 NetCDF、HDF4、HDF5、grib 等格式)的工具对我们的工作至关重要。

表 RCF-1.0:在 Xeon 节点上处理 NetCDF 文件所用的时间。

语言所用时间Python660.8084

Julia787.4500

IDL711.2615

R1220.222

Matlab848.5086

表 RCF-1.1:在 i7 Mac 上处理 NetCDF 文件所用的时间。

语言所用时间Python89.1922

表 RCF-2.0:在 Xeon 节点上利用多核处理器使用 Python 处理 NetCDF 文件所用的时间。

核所用时间1570.9791

2317.6108

4225.4647

8147.4527

1684.0102

2459.7646

2851.2191

表 RCF-2.1:在 i7 Mac 上利用多核处理器使用 Python 处理 NetCDF 文件所用的时间。

核所用时间184.1032

263.5322

456.6156

图表总结

在下面的图中,我们通过使用 GCC 获得的计时数字(仅在最后一列,即最大问题的大小)作为参考,总结上述计时结果。

b563a00e3e031ee49268aef0c46bf686.png

b563a00e3e031ee49268aef0c46bf686.png

研究结果

概述:

没有任何一种语言在所有测试中都优于其他语言。

通过仅在必要时创建变量以及“清空”不再使用的变量来减少内存占用非常重要。

对于相同的任务,使用内置函数会比内联代码带来更高的性能。

Julia 和 R 提供了简单的基准测试工具。我们编写了一个简单的 Python 工具,允许我们随心所欲地多次运行 Python 测试用例。

循环和向量化:

与使用循环相比,Python(和 NumPy)、IDL 和 R 在向量化时运行速度更快。

在使用 Numba 时,只要使用 NumPy 数组,Python 就可以更快地处理循环。

对于 Julia,循环比向量化代码运行得更快。

在不涉及计算的情况下,使用循环与向量化相比,MATLAB 在性能上似乎没有显著变化。当进行计算时,向量化 MATLAB 代码要比迭代代码更快。

字符串操作:

与其他语言相比,Java 和 Scala 在操作大型字符串时,似乎具有显著的性能。

数值计算:

与其他语言相比,R 在使用递归时似乎具有显著的性能。

语言在数值计算中相对于其他语言的性能表现取决于具体的任务。

MATLAB 的内置快速傅里叶变换函数似乎运行速度最快。

输入 / 输出:

虽然有些语言运行测试的速度比其他语言快,但在本地 Mac 上而不是处理器节点上运行测试的话,可以获得最大的性能提升。因为处理器节点使用机械硬盘,而 Mac 用的是固态硬盘。这表明硬件对 I/O 性能的影响比所使用的语言更大。

参考资料

Julia, Matlab and C,Justin Domke 著,2012 年 9 月 17 日

四阶泊松求解器,《计算物理学杂志》,55(1):166-172,Murli M. Gupta 著,1984 年

原文链接:

本文由 @张飞驰 发布于 职涯宝 ,未经作者许可,禁止转载,欢迎您分享文章

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值