How to get rid of a loop that depends on its previous iterations

조회 수: 2 (최근 30일)
JPL
JPL 2021년 10월 19일
댓글: JPL 2021년 10월 25일
I have an old c++ program that I want to translate to Matlab. It has a loop in which every iteration depends on a decision in the previous iteration. I have a lot of data, so it takes a long time. Is there a way to do this with matrix operations instead of a loop? Here's the code:
data = rand(1,105);
for k = 100 : -1 : 6
lowerAverage = mean(data(k-5:k-1));
upperAverage = mean(data(k+1:k+5));
surroundingAverage = mean([lowerAverage,upperAverage]);
if data(k) > surroundingAverage
data(k) = upperAverage
end
end
Thanks in advance.

채택된 답변

Jan
Jan 2021년 10월 19일
편집: Jan 2021년 10월 20일
Start with calculating the average manually instead of the slower mean() function:
% Timings: R2018b, Win10, i7
data0 = rand(1, 100005);
data = data0;
tic;
for k = 100000 : -1 : 6
lowerAverage = mean(data(k-5:k-1));
upperAverage = mean(data(k+1:k+5));
surroundingAverage = mean([lowerAverage,upperAverage]);
if data(k) > surroundingAverage
data(k) = upperAverage;
end
end
toc % Elapsed time is 1.050304 seconds.
data_orig = data;
data = data0;
tic;
for k = 100000 : -1 : 6
lowerAverage = sum(data(k-5:k-1)) / 5;
upperAverage = sum(data(k+1:k+5)) / 5;
surroundingAverage = (lowerAverage + upperAverage) / 2;
if data(k) > surroundingAverage
data(k) = upperAverage;
end
end
toc % Elapsed time is 0.050326 seconds.
isequal(data, data_orig) % true
20 times faster already. Mayby this is some percent faster:
data = data0;
tic;
for k = 100000 : -1 : 6 % 1 multiplication, 1 division:
low = sum(data(k-5:k-1));
up = sum(data(k+1:k+5));
if 10 * data(k) > (low + up)
data(k) = up / 5;
end
end
toc % Elapsed time is 0.049661 seconds.
The lower average is not influenced by overwriting the data. So this can be vectorized:
data = data0;
tic;
lowv = conv(data, ones(1, 5), 'same');
for k = 100000 : -1 : 6
low = lowv(k - 3);
up = sum(data(k+1:k+5));
if 10 * data(k) > (low + up)
data(k) = up / 5;
end
end
toc % Elapsed time is 0.025510 seconds.
The last method takes significantly more time when I run it in the forums MATLAB online 2021b. So try this locally on your computer.
[EDITED] If replacing mean() increases the speed, try this with sum() also:
data = data0;
tic;
avg = conv(data, ones(1, 5), 'same');
for k = 100000 : -1 : 6
low = avg(k - 3);
up = data(k+1) + data(k+2) + data(k+3) + data(k+4) + data(k+5);
if 10 * data(k) > (low + up)
data(k) = up / 5;
end
end
toc % Elapsed time is 0.007511 seconds.
A speedup of factor 140 on my R2018b and the random test data.
  댓글 수: 5
Jan
Jan 2021년 10월 22일
A mex version needs about half of the processing time compared to the last M-version of my asnwer:
#include "mex.h"
mvoid mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *X, low, up;
mwSize i, n;
n = mxGetNumberOfElements(prhs[0]);
plhs[0] = mxDuplicateArray(prhs[0]);
X = mxGetDoubles(plhs[0]);
for (i = n - 6; i > 4; i--) {
low = X[i-5] + X[i-4] + X[i-3] + X[i-2] + X[i-1];
up = X[i+1] + X[i+2] + X[i+3] + X[i+4] + X[i+5];
if (10 * X[i] > low + up) {
X[i] = up / 5;
}
}
return;
}
JPL
JPL 2021년 10월 25일
Thanks,
I think this will work out well.
John

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

태그

제품


릴리스

R2017a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by