递归循环优化

时间:2013-05-30 16:12:36

标签: matlab optimization

有没有办法重写我的代码以使其更快?

for i = 2:length(ECG)
    u(i) = max([a*abs(ECG(i)) b*u(i-1)]);
end;

我的问题是心电图的长度。

2 个答案:

答案 0 :(得分:2)

您应该像这样预先分配u

>> u = zeros(size(ECG));

或者可能喜欢这个

>> u = NaN(size(ECG));

或者甚至可能喜欢这个

>> u = -Inf(size(ECG));

取决于您想要的行为。

当你预先分配一个向量时,MATLAB知道向量的大小,并保留一个适当大小的内存块。

如果你没有预先分配,那么MATLAB无法知道最终的矢量有多大。最初它将分配一小段内存。如果该块中的空间不足,则必须在某处找到更大的内存块,并将所有旧值复制到新的内存块中。每次在分配的块中用完空间时都会发生这种情况(这可能不是每次增长数组时都是如此,因为MATLAB运行时可能足够聪明,需要的内存比它需要的多一点,但它仍然不止于必要)。所有这些不必要的重新分配和复制都需要很长时间。

答案 1 :(得分:2)

有几种方法可以优化这个for循环,但是,令人惊讶的是,内存预分配不是节省大部分时间的部分。到目前为止。您正在使用max来查找1 x 2向量的最大元素。在每次迭代中,您都会构建此向量。但是,你所做的只是比较两个标量。使用max的两个参数形式并将其传递给两个标量的速度要快得多:在我的机器上使用大ECG个矢量快75倍以上!

% Set the parameters and create a vector with million elements
a = 2;
b = 3;
n = 1e6;
ECG = randn(1,n);

ECG2 = a*abs(ECG); % This can be done outside the loop if you have the memory
u(1,n) = 0;        % Fast zero allocation
for i = 2:length(ECG)
    u(i) = max(ECG2(i),b*u(i-1)); % Compare two scalars
end

对于max的单一输入形式(不包括随机ECG数据的创建):

Elapsed time is 1.314308 seconds.

对于我上面的代码:

Elapsed time is 0.017174 seconds.

仅供参考,上面的代码假定为u(1) = 0。如果不是这样,那么在预分配之后应该将u(1)设置为它的值。