Performance – How to vectorize many ranked first external products?

Can the following loop be vectorized? Each iteration in the loop forms an outer product, then symmetric and store the result as a column in a matrix. Expect m to be large (e.g., 1e4) and s to be small (e.g., 10).

% U and V are m-by-s matrices
A = zeros(s^2, m);% preallocate
for k = 1:m
Ak = U(k,:)' * V(k,:);
Ak = (Ak + Ak')/2;
A(:, k) = Ak(:);
end

Edit

The following is a comparison of 3 different methods: iterative large dimension m, iterative small dimension s and the solution based on bsxfun (accepted and fastest answer) .

s = 5; m = 100000;
U = rand(m, s);
V = rand(m, s);< br />
% Iterate over large dimension
tic
B = zeros(s^2, m);
for k = 1:m
Ak = U( k,:)' * V(k,:);
Ak = (Ak + Ak')/2;
B(:, k) = Ak(:);
end< br />toc

% Iterate over small dimension
tic
A = zeros(s, s, m);
for i = 1:s
A(i,i,:) = U(:, i) .* V(:, i);
for j = i+1:s
A(i,j,:) = (U(:,i).*V(:,j) + U(:, j).*V(:, i))/2;
A(j,i,:) = A(i ,j,:);
end
end
A = reshape(A, [s^2, m]);
toc

% bsxfun -based solution
tic
A = bsxfun( @times, per mute( U, [1 3 2] ), permute( V, [1 2 3]) );
A = .5 * (A + permute( A, [1 3 2]) );
B = reshape( A, [m, s^2] )';
toc

This is a time comparison:

Elapsed time is 0.547053 seconds.
Elapsed time is 0.042639 seconds.
Elapsed time is 0.039296 seconds.

Use bsxfun (this is how it is done with a lot of fun):

% the outer product
A = bsxfun( @times, permute( U, [1 3 2] ), permute( V, [1 2 3]) );
% symmetrization
A = .5 * (A + permute( A, [1 3 2] ) );
% to vector (per product)
B = reshape( A, [ms^2] )';

Benchmark test results (my machine):

>Original method (iterative big dim):

Elapsed time is 0.217695 seconds.

>”New” method (smaller iteration) Dim):

Elapsed time is 0.037538 seconds.

>Interesting bsxfun:

 Elapsed time is 0.021507 seconds.

As you can see, bsxfun needs ~2 / 3-1/2 of the fastest cycle…

Isn’t bsxfun fun?

Can the following loop be vectorized? Each iteration in the loop forms an outer product, then symmetric and store the result as a column in a matrix. Expect m to be large (e.g., 1e4) and s to be small (e.g., 10).

% U and V are m-by-s matrices
A = zeros(s^2, m);% preallocate
for k = 1:m
Ak = U(k,:)' * V(k,:);
Ak = (Ak + Ak')/2;
A(:, k) = Ak(:);
end

Edit

The following is a comparison of 3 different methods: iterative large dimension m, iterative small dimension s and the solution based on bsxfun (accepted and fastest answer) .

s = 5; m = 100000;
U = rand(m, s);
V = rand(m, s);< br />
% Iterate over large dimension
tic
B = zeros(s^2, m);
for k = 1:m
Ak = U( k,:)' * V(k,:);
Ak = (Ak + Ak')/2;
B(:, k) = Ak(:);
end< br />toc

% Iterate over small dimension
tic
A = zeros(s, s, m);
for i = 1:s
A(i,i,:) = U(:, i) .* V(:, i);
for j = i+1:s
A(i,j,:) = (U(:,i).*V(:,j) + U(:, j).*V(:, i))/2;
A(j,i,:) = A(i ,j,:);
end
end
A = reshape(A, [s^2, m]);
toc

% bsxfun -based solution
tic
A = bsxfun( @times, permute( U , [1 3 2] ), permute( V, [1 2 3]) );
A = .5 * (A + permute( A, [1 3 2]) );
B = reshape( A, [m, s^2] )';
toc

This is a time comparison:

Elapsed time is 0.547053 seconds.
Elapsed time is 0.042639 seconds.
Elapsed time is 0.039296 seconds.

Use bsxfun (this is how it is done a lot Fun):

% the outer product
A = bsxfun( @times, permute( U, [1 3 2] ), permute( V, [1 2 3]) );
% symmetrization
A = .5 * (A + permute( A, [1 3 2]) );
% to vector (per product)< br />B = reshape( A, [ms^2] )';

Benchmark test results (my machine):

>Original method (iteration big dim):< /p>

Elapsed time is 0.217695 seconds.

>”New” method (with smaller iterations):

Elapsed time is 0.037538 seconds.

>Interesting bsxfun:

Elapsed time is 0.021507 seconds.

As you As you can see, bsxfun needs ~2 / 3-1/2 of the fastest cycle…

Isn’t bsxfun very interesting?

Leave a Comment

Your email address will not be published.