罗兰在MATLAB的艺术

把想法变成MATLAB

一个典型案例研究使MATLAB代码更快

今天我想欢迎嘉宾博客 迈克裘槎 最近加入MathWorks经过长时间的职业生涯作为一个客户成功工程师支持学术计算研究。金宝app

介绍

大多数我的职业生涯一直致力于与科学家和工程师合作,提高他们的计算工作流。有许多可以做的事情包括鼓励使用版本控制或 单元测试 但是,到目前为止,最常见的请求 “你能做这件事我再快呢?”
二十多年的问这个简单的问题使我探索技术计算的许多领域如并行计算、数值分析, 高性能计算和云计算 , GPU计算 、数学优化 自动分化 和多种语言等等。
在其核心,使一个程序更快的艺术归结为遍历两个简单的步骤。
  1. 找出什么是缓慢的。
  2. 尝试不一样的东西,看看它的任何更快的同时还能给予正确的答案
你可能会想象,有一个世界的复杂性隐藏在上面。尝试不同的可能意味着使用语言特性来优化算法我写,尝试parallelisation althogether甚至切换到一个完全不同的算法。我通常会添加一个额外的约束点2的消耗尽可能少的努力因为我根本懒。
MATLAB的分析器 最近收到一个接口改革 提供火焰图视图代码的执行时间,帮助照顾第一点。探索bloggable的分析器将提供丰富的seam将探索所有的内容 算法性能增强 我们从一个版本发布。
多亏了 MATLAB执行引擎 (以前在这个博客上讨论 在这里 在这里 ), 其他优化 ,现代MATLAB比以往任何时候都更快,如下图所示,我们在这方面不断改进。
当然总有很多时候我们需要优化我们的代码的速度,我想分享一个例子最近在内部讨论。

不要害怕许晴

灵感来自这篇文章 ,写了下面的一个同事在MATLAB计算素数。
类型myCountPrimes.m
%计算有多少个质数包括max_n函数res = myCountPrimes (max_n) res = 0;因为我= 2:max_n如果MyIsPrime res = res + 1;端端端%函数检查n是否'结果= MyIsPrime (n)如果n < = 1 = false结果;返回结束q =地板(sqrt (n));因为我= 2:问如果国防部(n, i) = = 0 = false结果;返回最终结果= true;结束
numPrimes = myCountPrimes (1000000)
numPrimes = 78498
这段代码很重循环——确切的东西我在早期MATLAB被训练来避免但由于执行引擎,这不是太糟糕了。(见 最近的文章更多循环的速度 在MATLAB)
f = @ () myCountPrimes (1000000);
originalSpeed时间= (f)
originalSpeed = 3.7878
即便如此,有许多事情我们可以尝试加快这一特定的代码。我们可以利用循环的每次迭代的事实 myCountPrimes 是独立的,使用平行 parfor循环 。这很容易做到,但可能需要大量的计算资源。一旦你意识到你可以利用 parfor ,就容易让你的问题消失,把尽可能多的CPU核。这些天我最喜欢的方法是火了 云中心集群 和增加核心数高达是有意义的。

改变国防部地板上

分析器显示我,很多时间都花在了线
如果国防部(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 parallelisation仍在桌子上如果我们需要更多的速度。

MATLAB算法的存储库

最后,我们可以认识到,我们正在使用的基本算法计算素数不是最优,转而使用一个不同的人。采取这样的极端,我们可以记住MATLAB数值算法的存储库以及一种编程语言,所以直接找到一个解决我们想要解决的问题,而不是我们自己的。揭示了一个快速搜索的文档 质数 素数的函数,返回一个数组。我们生产这个数组和计算元素如下所示。
numPrimes =元素个数(质数(1000000))
numPrimes = 78498
f = @()元素个数(质数(1000000));
builtinSpeed时间= (f)
builtinSpeed = 0.0029
超过足够快我的目的!

系统信息

如果你自己的机器上运行此脚本,你几乎肯定会得到不同的结果。使用 版本 功能和优秀的 CPU信息 通过本Tordoff,这里有我的机器和MATLAB版本的细节。
versionInfo = [“MATLAB释放R”版本(“发布”)]
versionInfo =“R2021a MATLAB版本”
cpuinfo ()
ans =结构体字段:
名称:“英特尔(R) (TM)核心i7 - 8650 u @ 1.90 ghz CPU的时钟:“2112 MHz的缓存:1024 KB的NumProcessors: 4 OSType:“Windows”OSVersion:“微软视窗10 Pro”

你的需要,一种加速的需要吗?

MATLAB是比以往任何时候都更快,它将继续在未来更快。结合改进的硬件,这将帮助你的答案比你以往任何时候都更大、更复杂的问题。然而,总会有场合,我们需要更多。MATLAB加速技术做什么你觉得有用,你希望在MATLAB更快吗?让我们知道 在这里
辅助函数
函数结果= floorMyIsPrime (n)
如果n是' %功能检查
如果n < = 1
结果= false;
返回
结束
q =地板(sqrt (n));
我= 2:问
如果地板(n / i) = = n /我
结果= false;
返回
结束
结束
结果= true;
结束
函数res = floorMyCountPrimes (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
res = 0;
我= 2:max_n
如果uint32MyIsPrime(我)
res = res + 1;
结束
结束
结束
版权2021年MathWorks公司。
|

评论

留下你的评论,请点击在这里MathWorks账户登录或创建一个新的。