Performance 修改阵列的函数意外减速
这个错误是由于Matlab太聪明了 我有点像Performance 修改阵列的函数意外减速,performance,matlab,Performance,Matlab,这个错误是由于Matlab太聪明了 我有点像 for k=1:N stats = subfun(E,k,stats); end 其中,stats是一个1xN数组,N=5000假设,subfun从E计算stats(k),并将其填充到stats中 function stats = subfun(E,k,stats) s = mean(E); stats(k) = s; end 当然,在来回传递一个大数组时,只需填充其中一个元素,会有一些开销。然而,在我的例子中,开销是可以
for k=1:N
stats = subfun(E,k,stats);
end
其中,stats
是一个1xN
数组,N=5000
假设,subfun
从E
计算stats(k)
,并将其填充到stats中
function stats = subfun(E,k,stats)
s = mean(E);
stats(k) = s;
end
当然,在来回传递一个大数组时,只需填充其中一个元素,会有一些开销。然而,在我的例子中,开销是可以忽略的,我更喜欢这段代码而不是
for k=1:N
s = subfun(E,k);
stats(k) = s;
end
我的偏好是因为我实际上有比统计数据多得多的任务。
另外,有些作业实际上要复杂得多
如前所述,开销是可以忽略的。但是,如果我做了一些琐碎的事情,比如这个无关紧要的if语句
for k=1:N
i = k;
if i>=1
stats = subfun(E,i,stats);
end
end
子单元内部发生的赋值突然“永远”(其增长速度远远快于与N的线性关系)。这是一项任务,而不是永远需要的计算。事实上,它甚至比以下毫无意义的子功能更糟糕
function stats = subfun(E,k,stats)
s = calculation_on_E(E);
clear stats
stats(k) = s;
end
每次都需要重新分配统计数据
有人知道为什么会发生这种情况吗?这可能是由于Matlab的一些模糊细节造成的。Matlab最新版本的JIT不知道创建新数组,而是在某些有限的情况下进行修改。其中一个要求是将功能定义为
function x = modify_big_matrix(x, i, j)
x(i, j) = 123;
而不是
function x_out = modify_big_matrix(x_in, i, j)
x_out = x_in;
x_out(i, j) = 123;
您的示例似乎遵循这条规则,因此,正如Praetorian所提到的,您的if
语句可能会阻止JIT认识到它是一个就地操作
如果您真的需要加快算法的速度,可以在适当的位置修改数组。我已经成功地使用这个技巧在一些中型阵列(订单100x100x100 IIRC)上获得了4倍的加速。但是,如果您不小心,这可能会破坏Matlab,并可能在未来版本中停止工作。正如其他人所讨论的,问题几乎肯定在于JIT及其相对脆弱的修改能力
如前所述,我确实更喜欢函数调用和赋值的第一种形式,尽管已经提出了其他可行的解决方案。在不依赖JIT的情况下,唯一有效的方法(据我所见)是某种形式的引用传递
因此,我创建了一个从handle继承的类Stats
,它包含k=1:N
的数据数组。然后通过引用传递它
作为将来的参考,这似乎工作得很好,性能也很好,我目前正在使用它作为我的工作解决方案。什么是E
?只是一些常量数据?E
可能是常量,也可能是随机的。它的大小不变。查看我的编辑。Matlab最新版本的JIT知道不创建新数组,而是进行修改。其中一个要求是将函数定义为函数x=modify(x,y)
,而不是函数x\u out=modify(x\u in,y)
。您的示例似乎遵循这条规则,但您是否检查了实际代码?正如@Bas所提到的,MATLAB内置了一些启发式方法来确定是否可以修改数组。我猜通过在循环中添加分支,您已经混淆了JIT,它不再认为就地修改是可能的,从而导致每次迭代都重新分配。假设MATLAB没有函数的参考参数的概念,那么您真的应该重写函数,以便调用stats(k)=subfun(E,k)代码>在循环中。这将是更好的实践,而不是依赖JIT和它的模式匹配(或任何它做的事情)。@Praetorian我考虑过这一点,但问题是我的统计数据实际上是一个包含多个数组的结构。我当然可以有一个结构数组,但我发现从这样一个对象中获取字段更难。你的意思是function x=modify(x,y)
,而不仅仅是x=modify(x,y)
,对吗?是的,我的真实代码也有所需的格式。虽然我认为是JIT搞糟了,但是if语句真的很奇怪,谢谢,修正了错误。