Я подхожу к точно такой же проблеме, ориентируясь на наиболее эффективный метод. Есть примерно три подхода, которые я вижу, за исключением использования внешних библиотек (то есть mtimesx ):
- Цикл срезов трехмерной матрицы
- Колдовско-перестановочное волшебство
- умножение на ячейки
Недавно я сравнил все три метода, чтобы увидеть, какой из них был самым быстрым. Моя интуиция заключалась в том, что (2) будет победителем. Вот код:
% generate data
A = 20;
B = 30;
C = 40;
D = 50;
X = rand(A,B,C);
Y = rand(B,D);
% ------ Approach 1: Loop (via @Zaid)
tic
Z1 = zeros(A,D,C);
for m = 1:C
Z1(:,:,m) = X(:,:,m)*Y;
end
toc
% ------ Approach 2: Reshape+Permute (via @Amro)
tic
Z2 = reshape(reshape(permute(X, [2 1 3]), [A B*C]), [B A*C])' * Y;
Z2 = permute(reshape(Z2',[D A C]),[2 1 3]);
toc
% ------ Approach 3: cellfun (via @gnovice)
tic
Z3 = cellfun(@(x) x*Y,num2cell(X,[1 2]),'UniformOutput',false);
Z3 = cat(3,Z3{:});
toc
Все три подхода дали одинаковый результат (фу!), Но, что удивительно, цикл оказался самым быстрым:
Elapsed time is 0.000418 seconds.
Elapsed time is 0.000887 seconds.
Elapsed time is 0.001841 seconds.
Обратите внимание, что время может сильно варьироваться от одного испытания к другому, и иногда (2) получается самое медленное. Эти различия становятся более существенными с большими данными. Но с намного большими данными, (3) удары (2). Метод цикла все еще лучший.
% pretty big data...
A = 200;
B = 300;
C = 400;
D = 500;
Elapsed time is 0.373831 seconds.
Elapsed time is 0.638041 seconds.
Elapsed time is 0.724581 seconds.
% even bigger....
A = 200;
B = 200;
C = 400;
D = 5000;
Elapsed time is 4.314076 seconds.
Elapsed time is 11.553289 seconds.
Elapsed time is 5.233725 seconds.
Но метод цикла может быть медленнее, чем (2), если зацикленное измерение намного больше, чем другие.
A = 2;
B = 3;
C = 400000;
D = 5;
Elapsed time is 0.780933 seconds.
Elapsed time is 0.073189 seconds.
Elapsed time is 2.590697 seconds.
Итак (2) выигрывает с большим фактором, в этом (может быть, крайнем) случае. Может не быть подхода, который был бы оптимальным во всех случаях, но цикл все еще довольно хорош, а во многих случаях лучше. Это также лучше с точки зрения читабельности. Отойди!