matlab length_[高性能实战案例] MATLAB,Julia, Python(Numba)

a02263ce4551fd822c9fdb0151483efe.png

实战案例题目为:

Problem 249 - Project Euler​projecteuler.net

虽然说Project Euler官方不鼓励用户公开答案或者代码, 但是, 这个属于陈年老题, 网上答案一大堆, 不差我一个, 而且题目难度也不大(难度等级为60%, 最高为100%, 最低为5%), 就违规一次, 将它作为讲解的案例题目好了.

本文章就不解释题目的算法了, 而是从程序代码实现的层面来讲解Julia的一些优化技巧.

废话不多说, 先贴代码, 再解释.

1 MATLAB的向量化版:

function 

运行结果:

10.207570 秒。

如果是循环版的话, 时间得乘以100, 循环版代码我就不贴了.

2 Julia的向量化版:

using 

运行结果:

julia

3 Julia的loop版:

function 

运行结果:

julia

4 Julia的loop2版:

function 

运行结果:

julia

5 Julia的loop3版:

function 

运行结果:

julia

结果汇总一下(取平均值, 单位是秒):

  1. MATLAB的向量化版: 10.207570
  2. Julia的向量化版: 5.251
  3. Julia的loop版: 2.952
  4. Julia的loop2版: 1.731
  5. Julia的loop3版: 0.321392

MATLAB版本为R2018b

Julia版本为1.0.1

下面是讲解部分:

1 Julia的向量化版是MATLAB的向量化版的最直接翻译, 速度快了进一倍, 我估计是因为MATLAB的mod函数太慢.

2 Julia的loop版是Julia的向量化版最直接的转换, 速度又提升了近一倍.

3 Julia的loop2版相比Julia的loop版差别就在求余运算上, 将求余"%"改为了减法"-", 速度又提升了近一倍.

4 Julia的loop3版相比Julia的loop2版, 差别就在使用了宏命令"@inbounds"和"@simd", 速度提升到了5倍多. 这个有些让我吃惊.

"@inbounds"的意思是: 不负责检查索引号是否越界了, 让用户自己去确保那些索引号是不越界的, 万一一不小心越界了, 有可能让程序崩溃.

这个特性和C/C++的数组很像.

为了速度, 冒着程序崩溃的风险还是值得的, 更何况之前写了那么多的版本, 已经能够确保不越界了.

"@simd"的意思是: 编译器重新制定一个顺序(不一定是乱序, 根据需要, 可能是有规律的), 而不是for循环里面的顺序, 目的是有利于CPU的向量化(具体我也不太懂, 有兴趣的, 可以自己查资料).

具体到程序, 求和并不依赖于执行顺序的, 因为加法运算符合"交换律".

另外:

一个网友用C++写了程序, 在他电脑上运行时间为0.171秒.

假设按照主频进行线性换算, 他那个0.171到我这要0.19秒,

我的Julia时间是0.32秒, 2倍以内, 我已经很满意了.

总结:

1 Julia的循环比MATLAB的循环速度快得多, 当程序无法进行向量化运算的时候, Julia相比MATLAB就体现出了优势了.

2 Julia的优化技巧相比MATLAB多得多.

比如这里用到的宏命令"@inbounds"和"@simd", MATLAB就没有对等的.

还有很多其他技巧, 我会在以后提到.

3 Julia的性能测试相比MATLAB更加注重"内存".

---2018年12月28日更新------------------------------

关于SIMD, 补充一些知识(来自于教材"Julia High Performance"中的113/132):

SIMD提速的本质是: 处理器一个周期能够计算多个数字, 如果按照for循环一次让它计算一个数字, 就是计算资源的浪费. "@simd"就是让处理器一次能计算多个数字, 充分利用它的计算能力.

@simd能够提速的前提条件(只是列举一些, 不是全部):

1 for循环loop之间是相互独立的.

2 循环体里面没有分支结构(if, else), 也没有函数调用.

3 循环的次数是明显的.

4 循环的步长为1

5 边界检查必须关闭. 也就是说" @simd"必须配合"@inbounds".

关于第5点, 我之前的实验发现了这种现象:

测试代码:

using 

测试性能:

using 

2019-12-3更新

Python 

aa231114ace22248e27b0d947111cadc.png

警告:

稍微有一些赖皮, 因为求质数的部分移到了函数外面去, 因为如果在函数内部的话, numba老是会出现警告信息.

但考虑到程序的瓶颈不在求质数的部分, 因此, 赖皮的程度是可以接受的, 其他语言求不再修改重新测试了.

测试了一下求质数的部分:

ffd851e71c681fb038a2c79119d12113.png

发现这部分确实不是性能瓶颈. 因此, 我将它们移除函数进行测试, 问题不大.

结果汇总一下(取平均值, 单位是秒):

  1. MATLAB的向量化版: 10.207570
  2. Julia的向量化版: 5.251
  3. Julia的loop版: 2.952
  4. Julia的loop2版: 1.731
  5. Julia的loop3版: 0.321392
  6. Python的numba版: 0.477

MATLAB版本为R2018b

Julia版本为1.0.1

Python 3.7.3

Numba 0.46.0

Python的numba版稍慢于Julia的loop3版.

但快于Julia的其他版本.

我觉得主要原因是因为numba版没有"关闭边界检查"的命令, 也没有"simd"命令.

但整体性能上还是让人满意的.

相关文章:

haitao:Julia, Python(Numba), C++, MATLAB 性能测试之“冰雹数”​zhuanlan.zhihu.com
d0bd2a1fd8fef4d7c889248c3139a06f.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值