Вот мой тест методов, упомянутых до сих пор, вместе с несколькими моими дополнениями:
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