how to vectorize these "for loop"?

1 Ansicht (letzte 30 Tage)
nelson
nelson am 5 Aug. 2017
Kommentiert: nelson am 5 Aug. 2017
clear all;
close all;
clc;
i=1;
for k=1:0.5:10;
for a=1:0.5:10;
for b= 1:0.5:10;
num(i,:)=[ k k*a];
den(i,:)=[1 b 0];
i=i+1;
end
end
end
[EDITED, Jan, Code formatted]

Akzeptierte Antwort

Andrei Bobrov
Andrei Bobrov am 5 Aug. 2017
My "ruble".
[b,a,k] = ndgrid(1:.5:10);
n = numel(k);
num1 = [k(:),k(:).*a(:)];
den1 = [ones(n,1), b(:), zeros(n,1)];
  2 Kommentare
Jan
Jan am 5 Aug. 2017
+1: This looks nice and clean. It is just 0.008 sec slower (for 100 iterations!) than the fastest solution I've found, but expanding, debugging and maintaining this nicer code will save at least minutes.
30% faster with explicite pre-allocation:
[b,a,k] = ndgrid(1:.5:10);
n = numel(k);
num = zeros(n, 2);
num(:,1) = k(:);
num(:,2) = k(:) .* a(:);
den = zeros(n, 3);
den(:,1) = 1;
den(:,2) = b(:);
But again: less nice and more prone to typos.
nelson
nelson am 5 Aug. 2017
thanks....

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Jan
Jan am 5 Aug. 2017
Bearbeitet: Jan am 5 Aug. 2017
The loops are not the main problem here, but the missing pre-allocation.
n = 19^3;
num = zeros(n, 2); % <-- Inserted
den = zeros(n, 3); % <-- Inserted
i = 1;
for k = 1:0.5:10
for a = 1:0.5:10
for b = 1:0.5:10
num(i, :) = [k, k*a];
den(i, :) = [1, b, 0];
i = i + 1;
end
end
end
Now take a look in the data: all den(:, 1) are 1, all den(:, 3) are 0, and the 2nd component is a repeated 1:0.5:10. This can be abbreviated:
v = 1:0.5:10;
n = length(v);
den = zeros(n^3, 3);
den(:, 1) = 1;
den(:, 2) = repmat(v, 1, n^2);
For num:
num = zeros(n^3, 2);
num(:, 1) = repelem(v.', n^2, 1); % REPELEM in >= R2015a
tmp = repelem(v.', n, 1) * v; % Auto-Expand in >= R2016b
num(:, 2) = tmp(:);
For older Matlab versions:
num = zeros(n^3, 2);
num(:, 1) = reshape(repmat(v, n^2, 1), [], 1);
tmp1 = repmat(v, n, 1);
tmp2 = bsxfun(@times, tmp1(:), v);
num(:, 2) = tmp2(:);
Some timings (R2016b/64, Win7, Core2Duo):
tic; for k = 1:100, [d,n] = Untitled; end; toc
Elapsed time is 12.222231 seconds. % Original
Elapsed time is 0.779765 seconds. % Original with pre-allocation !!!
Elapsed time is 0.012142 seconds. % Vectorized >= 2016b
Elapsed time is 0.013797 seconds. % Vectorized <= 2015a
Elapsed time is 0.020055 seconds. % Andrei's solution
Pre-allocation yields a speed gain of factor 16, the vectorization a factor of 1000. Nice!
  3 Kommentare
Andrei Bobrov
Andrei Bobrov am 5 Aug. 2017
+1 Good work.
Jan
Jan am 5 Aug. 2017
Bearbeitet: Jan am 5 Aug. 2017
@nelson: Please try it again. I've fixed some typos since the first posting. I get:
v = 1:0.5:10;
n = length(v);
i=1;
for k=v, for a=v, for b=v
num(i,:)=[ k k*a];
i=i+1;
end, end, end
num2 = zeros(n^3, 2);
num2(:, 1) = repelem(v.', n^2, 1); % >= R2015a
tmp = repelem(v.', n, 1) * v; % >= R2016b
num2(:, 2) = tmp(:);
isequal(num, num2) % 1: okay

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Startup and Shutdown finden Sie in Help Center und File Exchange

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by