当前位置 : 主页 > 网络安全 > 测试自动化 >

性能 – 就地修改数组的函数意外减速

来源:互联网 收集:自由互联 发布时间:2021-06-22
这个错误是由于Matlab太聪明了. 我有类似的东西 for k=1:N stats = subfun(E,k,stats);end statsis a 1xNarray,N = 5000说,subfun从E计算stats(k),并将其填入统计数据 function stats = subfun(E,k,stats) s = mean(E); stats
这个错误是由于Matlab太聪明了.

我有类似的东西

for k=1:N
    stats = subfun(E,k,stats);
end

statsis a 1xNarray,N = 5000说,subfun从E计算stats(k),并将其填入统计数据

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

然后,在subfun内发生的任务突然变为“永远”(它比N线性地增加得快得多).这是任务,而不是永远的计算.事实上,它甚至比以下荒谬的subfun更糟糕

function stats = subfun(E,k,stats)
    s = calculation_on_E(E);
    clear stats
    stats(k) = s;
end

这需要每次重新分配统计数据.

有没有人知道为什么会这样?

这可能是由于Matlab的 JIT的一些模糊细节.近期版本的Matlab的JIT知道不创建新阵列,而是在某些有限的情况下进行修改 in-place.其中一个要求是将函数定义为

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识别它是一个就地操作.

如果你真的需要加速你的算法,可以就地修改数组using your own mex-functions.我已经成功地使用这个技巧在一些中型阵列上获得了4倍的加速(订购100x100x100 IIRC).然而,这是not recommended,如果你不小心可能会陷入困境,可能会在未来的版本中停止工作.

网友评论