Ето моя еталон за методите, споменати досега, заедно с няколко мои собствени допълнения:
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
Резултатите на моята машина:
>> 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)
(Тези времена могат леко да се променят между различните изпълнения, но това трябва да ни даде представа как се сравняват методите)
Обърнете внимание, че някои от тези методи ще причинят грешки при недостиг на памет за по-големи входове (например моето решение, базирано на repmat
, може лесно да изчерпи паметта). Други ще станат значително по-бавни за по-големи размери, но няма да възникнат грешки поради изчерпана памет (решението kron
например).
Мисля, че методът bsxfun
func2_bsxfun_3rd_dim
или простият for-цикъл func4_forloop_matrix
(благодарение на MATLAB JIT) са най-добрите решения в този случай.
Разбира се, можете да промените горните параметри за сравнение (размер на x
и A
) и да си направите собствени заключения :)
person
Amro
schedule
24.06.2014
new_matrix
в размер на(12*m,n)
, както казахте сами, и след това използване на индекси, за да кажете на вашияnew_matrix
къде искате да бъдат запазени тези елементи, напр. във вашия код, даден по-гореnew_matrix(((i-1)*12+1):(i*12))) = A.*x(i)
го написах точно тук, така че не съм сигурен дали работи. - person The Minion   schedule 22.05.20141*new_matrix
,2*new_matrix
3*new_matrix
...и т.н. някои други изчисления, за които не мога да разбера откъде идват. - person Sergio Haram   schedule 22.05.2014bsxfun
. - person Divakar   schedule 22.05.2014