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