为什么在MATLAB中,向量化代码比for循环运行更快?

24

我已经阅读过这篇文章,但我仍然不明白为什么向量化的代码更快。

在for循环中,我可以使用parfor进行并行计算。如果向量化的代码更快,是否意味着它自动并行化了?


下面给出的答案是正确的,但事实上我认为大矩阵操作可能实际上可以自动并行运行。 - Dennis Jaheruddin
3个回答

20

不行。您混淆了两个重要的概念:

  • MATLAB 的设计目的是快速执行向量操作。MATLAB 是一种解释型语言,这就是为什么其中的循环速度很慢的原因。为了解决这个问题,MATLAB 提供了极快(通常由 C 编写并针对特定架构进行优化)和经过充分测试的函数来操作向量。这里真的没有魔法,只是许多努力和不断改进的结果。

例如,请考虑以下微不足道的情况:

s=0;
for i=1:length(v),
    s = s+v(i);
end

sum(v)

为了证明这两个函数的运行时间差异,您应该使用tictoc。有大约10个类似的常用于向量操作的函数,例如:bsxfunrepmatlengthfind。向量化是有效使用MATLAB的标准部分。在您能够有效地向量化代码之前,您只是MATLAB世界中的游客,而不是公民。

  • MATLAB的最新版本提供parforparfor不是万能药,它是一种可以被使用和误用的工具(请尝试对上面的求和例子使用parfor)。不是所有的循环都可以并行化。 parfor 是设计用于任务并行类型的问题,其中循环的每次迭代互相独立。这是使用parfor -loop的一个关键要求。

虽然在许多情况下,parfor可以帮助很多,但可以进行大幅度优化的循环类型很少出现。


4
你错过了一个重要的事情 - Matlab 是一种解释性语言。这就是为令它的循环速度如此之慢的原因,特别是与其设计目的高度优化的矩阵操作相比。 - Leonid Beschastny
2
你可能还想补充一下,解释型语言中循环较慢的原因是每次函数调用都会带来一些开销。因此,当你使用一个包含一百万个元素的数组调用函数一次时,比起使用标量调用一百万次,速度要快得多。 - Jonas
1
请注意,repmat只在数组很大的情况下才更快。对于简单问题,for循环仍然更好。同样适用于for循环。parfor循环仅在问题需要大量计算时才能发挥良好作用。否则,parfor循环将花费太多低效的时间来分配作业到其他核心上。 - elwc
1
此外,Matlab现在内置了JIT编译器,可以显著缩小for循环和向量化代码之间的差距,正如我的答案所示。 - KlausCPH
直到您能够有效地进行矢量化编程,您才是 MATLAB 世界中的居民,而不是旅客。 - Luis Mendo
显示剩余2条评论

16

我同意carlosdc的回答。 然而,需要记住的是Matlab自6.5版本以来包含了一个JIT编译器,可以加速for循环等操作。

我对你的sum示例进行了快速测试,其中v有一百万个元素,测试结果如下:

  • sum(v):4.3毫秒
  • for循环版本:16毫秒
  • for循环版本,未开启JIT:966毫秒

可以通过以下方式打开或关闭JIT:

feature accel off
feature accel on

当然,通过向量化代码来提高四倍的性能仍然是值得的,但是对于那些本来就适合使用for循环的问题,我们不应该像过去一样害怕使用它们。通常情况下,良好向量化的代码往往可以同时更简单、更少出错、更快。


2

在现代计算机中,寄存器(临时存储器,用于数学计算等)具有许多位并可以同时操作多个数字。例如,如果您的数据是uint8(8位),则可以在一个CPU时钟中为每个数字添加一个数字,或者将它们全部放在寄存器中,并在一个CPU时钟中为所有数字加上一个数字。这样,您的工作速度比使用for循环快8倍。

这在某种意义上是并行化的,但不像parfor。Parfor使用计算机CPU的多个核心,而以上方法则更有效地使用一个核心。如果两者都使用,则可以实现更高的速度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接