使MATLAB代码运行更快的主要案例研究
简介
我职业生涯的大部分时间都致力于与科学家和工程师合作,以改进他们的计算工作流程。有很多事情可以做,包括鼓励使用版本控制或
单元测试
但是,到目前为止,最常见的请求是
“你能让我做的这个东西跑快一点吗?”
在其核心,使程序更快的艺术归结为两个简单步骤的迭代。
- 找出到底什么是慢的。
- 尝试一些不同的方法,看看在给出正确答案的同时是否会更快
正如你所想象的,上面隐藏着一个复杂的世界。“尝试不同的东西”可能意味着使用语言特性来优化我所编写的算法,尝试并行化,甚至切换到完全不同的算法。我通常会在第2点上添加一个额外的约束,即“花费尽可能少的努力”,因为我本质上是懒惰的。
当然,我们总是需要优化我们的代码以提高速度,我想分享一个最近内部讨论的例子。
不要害怕环形使者
受到这篇文章的启发
,我的同事用MATLAB写了下面的程序来计数质数。
类型myCountPrimes.m
numPrimes = myCountPrimes(1000000)
numPrimes = 78498
f = @() myCountPrimes(1000000);
originalSpeed = timeit(f)
originalSpeed = 3.7878
即便如此,我们还是可以尝试很多方法来加速这段特定的代码。我们可以利用这样一个事实,即循环的每一次迭代
myCountPrimes
是独立的还是平行的
parfor循环
.这很容易做到,但可能需要大量的计算资源。一旦你意识到你可以利用
parfor
,为了解决这个问题,你可能会抛出尽可能多的CPU内核。我最近最喜欢的方法就是
云中心集群
在合理范围内增加核心数量。
改变国防部来地板上
剖析师告诉我,很多时间都花在了这条线上
如果mod(n,i) == 0
所以一种方法是问
“我们能把这条线重写得更快一点吗?”
.并不总是很明显哪些替代方法可能有效,所以我经常简单地想出一个不同的方法来做某事并尝试一下。表达式的另一种写法
国防部(n, i) = = 0
是
Floor (n/i) == n/i
事实证明,它要快得多!我在
floorMyCountPrimes
函数,检查它是否给出正确的结果,并证明它确实快得多。
numPrimes = floorMyCountPrimes(1000000)
numPrimes = 78498
f = @() floorMyCountPrimes(1000000);
floorSpeed = timeit(f)
floorSpeed = 0.5296
为整数算法尝试整数类型
默认情况下,MATLAB中的所有数字都是浮点类型
双
这对于很多数值计算来说是很好的但是这里我们要处理的是一个纯整数算法。在代码中明确这一点有时会带来好处,这就是其中之一!事实证明
国防部
函数在处理浮点数时必须做的工作比这个特定示例严格必要的工作多得多。作为程序员,我知道我的算法完全是基于整数的,所以我可以切换到使用
uint32
对于一些变量。也就是说,我改变了的主循环
MyIsPrime
来
Q =√(n);
N = uint32(N);
为I = uint32(2):q
如果Mod (n,i) == 0
结果= false;
返回
结束
结束
这使得MATLAB可以使用专门的和更快的版本
国防部
函数,因为它现在知道我们处理的是整数而不是双精度对象。
我在
uint32MyIsPrime
函数定义在这篇文章的最后,并通过uint32调用它
MyCountPrimes。
首先让我们检查结果是否与原始函数一致,然后计时
numPrimes = uint32MyCountPrimes(1000000)
numPrimes = 78498
f = @() uint32MyCountPrimes(1000000);
uint32Speed = timeit(f)
uint32Speed = 0.5660
使用这种方法或基于地板的方法,我们实现了相对较少的工作和技术的显著性能提升,例如
parfor
如果我们需要更快的速度,并行化仍然是摆在桌面上的。
MATLAB作为算法库
最后,我们可以认识到,我们用来计算质数的基本算法并不是最优的,而是使用另一种算法。举个极端的例子,我们可以记住MATLAB是一个数值算法库,也是一种编程语言,所以要找到一个直接解决我们想要解决的问题的库,而不是自己动手。快速搜索文档可以发现
质数
返回质数数组的函数。我们生成这个数组并计算元素,如下所示。
numPrimes = nummel(质数(1000000))
numPrimes = 78498
F = @()数字(质数(1000000));
builtinSpeed = timeit(f)
builtinSpeed = 0.0029
对我来说已经足够快了!
系统信息
versionInfo = [MATLAB Release R版本(“发布”)]
cpuinfo ()
你对速度的需求?
MATLAB比以往任何时候都要快,而且在未来还会越来越快。这与改进的硬件相结合,将帮助您回答比以前更大更复杂的问题。然而,总有一些场合我们需要更多。你觉得MATLAB中哪些加速技术是有用的?你希望MATLAB中的哪些加速技术更快?让我们知道
在这里
.
辅助函数
函数result = floorMyIsPrime(n)
检查n是否是质数的函数
如果N <= 1
结果= false;
返回
结束
Q =√(n);
为I = 2:q
如果Floor (n/i) == n/i
结果= false;
返回
结束
结束
结果= true;
结束
函数res = floorMyCountPrimes(max_n)
计算在max_n以内有多少质数
Res = 0;
为I = 2:max_n
如果floorMyIsPrime(我)
Res = Res +1;
结束
结束
结束
函数result = uint32MyIsPrime(n)
检查n是否是质数的函数
如果N <= 1
结果= false;
返回
结束
Q =√(n);
N = uint32(N);
为I = uint32(2):q
如果Mod (n,i) == 0
结果= false;
返回
结束
结束
结果= true;
结束
函数res = uint32MyCountPrimes(max_n)
计算在max_n以内有多少质数
Res = 0;
为I = 2:max_n
如果uint32MyIsPrime(我)
Res = Res +1;
结束
结束
结束
The MathWorks, Inc.版权所有
评论
如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。