Here is my benchmark of the methods mentioned so far, along with a few additions of my own:
function [t,v] = testMatMult()
% data
%{
x = [1 2 3 4 5 6 7 8 9 10 11 12];
A = [11 14 1; 5 8 18; 10 8 19; 13 20 16];
%}
x = 1:50;
A = randi(100, [1000,1000]);
% functions to test
fcns = {
@() func1_repmat(A,x)
@() func2_bsxfun_3rd_dim(A,x)
@() func2_forloop_3rd_dim(A,x)
@() func3_kron(A,x)
@() func4_forloop_matrix(A,x)
@() func5_forloop_cell(A,x)
@() func6_arrayfun(A,x)
};
% timeit
t = cellfun(@timeit, fcns, 'UniformOutput',true);
% check results
v = cellfun(@feval, fcns, 'UniformOutput',false);
isequal(v{:})
%for i=2:numel(v), assert(norm(v{1}-v{2}) < 1e-9), end
end
% Amro
function B = func1_repmat(A,x)
B = repmat(x, size(A,1), 1);
B = bsxfun(@times, B(:), repmat(A,numel(x),1));
end
% Divakar
function B = func2_bsxfun_3rd_dim(A,x)
B = bsxfun(@times, A, permute(x, [3 1 2]));
B = reshape(permute(B, [1 3 2]), [], size(A,2));
end
% Vissenbot
function B = func2_forloop_3rd_dim(A,x)
B = zeros([size(A) numel(x)], 'like',A);
for i=1:numel(x)
B(:,:,i) = x(i) .* A;
end
B = reshape(permute(B, [1 3 2]), [], size(A,2));
end
% Luis Mendo
function B = func3_kron(A,x)
B = kron(x(:), A);
end
% SergioHaram & TheMinion
function B = func4_forloop_matrix(A,x)
[m,n] = size(A);
p = numel(x);
B = zeros(m*p,n, 'like',A);
for i=1:numel(x)
B((i-1)*m+1:i*m,:) = x(i) .* A;
end
end
% Amro
function B = func5_forloop_cell(A,x)
B = cell(numel(x),1);
for i=1:numel(x)
B{i} = x(i) .* A;
end
B = cell2mat(B);
%B = vertcat(B{:});
end
% Amro
function B = func6_arrayfun(A,x)
B = cell2mat(arrayfun(@(xx) xx.*A, x(:), 'UniformOutput',false));
end
The results on my machine:
>> t
t =
0.1650 %# repmat (Amro)
0.2915 %# bsxfun in the 3rd dimension (Divakar)
0.4200 %# for-loop in the 3rd dim (Vissenbot)
0.1284 %# kron (Luis Mendo)
0.2997 %# for-loop with indexing (SergioHaram & TheMinion)
0.5160 %# for-loop with cell array (Amro)
0.4854 %# arrayfun (Amro)
(Those timings can slightly change between different runs, but this should give us an idea how the methods compare)
Note that some of these methods are going to cause out-of-memory errors for larger inputs (for example my solution based on repmat
can easily run out of memory). Others will get significantly slower for larger sizes but won't error due to exhausted memory (the kron
solution for instance).
I think that the bsxfun
method func2_bsxfun_3rd_dim
or the straightforward for-loop func4_forloop_matrix
(thanks to MATLAB JIT) are the best solutions in this case.
Of course you can change the above benchmark parameters (size of x
and A
) and draw your own conclusions :)
new_matrix
in size of(12*m,n)
as you said yourself and then using indices to tell yournew_matrix
where you want these elements saved, e.g. in your code given abovenew_matrix(((i-1)*12+1):(i*12))) = A.*x(i)
i wrote it just here, so not sure if it works. – The Minion1*new_matrix
,2*new_matrix
3*new_matrix
...etc some other calculations which I can't tell where they come from. – Sergio Harambsxfun
. – Divakar