I have two 3-dimensional arrays, the first two dimensions of which represent matrices and the last one counts through a parameterspace, as a simple example take
A = repmat([1,2; 3,4], [1 1 4]);
(but assume A(:,:,j)
is different for each j
). How can one easily perform a per-j
matrix multiplication of two such matrix-arrays A
and B
?
C = A; % pre-allocate, nan(size(A,1), size(B,2)) would be better but slower
for jj = 1:size(A, 3)
C(:,:,jj) = A(:,:,jj) * B(:,:,jj);
end
certainly does the job, but if the third dimension is more like 1e3 elements this is very slow since it doesn't use MATLAB's vectorization. So, is there a faster way?
I highly recommend you use the MMX toolbox of matlab. It can multiply n-dimensional matrices as fast as possible.
The advantages of MMX are:
For this problem, you just need to write this command:
I added the following function to @Amro's answer
I got this result for
n=2,m=2,p=1e5
:I used @Amro's code to run the benchmark.
An even faster method, in my experience, is to use dot multiplication and summation over the three-dimensional matrix. The following function, function z_matmultiply(A,B) multiplies two three dimensional matrices which have the same depth. Dot multiplication is done in a manner that is as parallel as possible, thus you might want to check the speed of this function and compare it to others over a large number of repetitions.
I did some timing tests now, the fastest way for 2x2xN turns out to be calculating the matrix elements:
In the general case it turns out the for loop is actually the fastest (don't forget to pre-allocate C though!).
Should one already have the result as cell-array of matrices though, using cellfun is the fastest choice, it is also faster than looping over the cell elements:
However, having to call num2cell first (
Ac = num2cell(A, [1 2])
) andcell2mat
for the 3d-array case wastes too much time.Here's some timing I did for a random set of 2 x 2 x 1e4:
Explicit refers to using direct calculation of the 2 x 2 matrix elements, see bellow. The result is similar for new random arrays,
cellfun
is the fastest if nonum2cell
is required before and there is no restriction to 2x2xN. For general 3d-arrays looping over the third dimension is indeed the fastest choice already. Here's the timing code:Here is my benchmark test comparing the methods mentioned in @TobiasKienzler answer. I am using the TIMEIT function to get more accurate timings.
The results:
As I explained in the comments, a simple FOR-loop is the best solution (short of loop unwinding in the last case, which is only feasible for these small 2-by-2 matrices).
One technique would be to create a 2Nx2N sparse matrix and embed on the diagonal the 2x2 matrices, for both A and B. Do the product with sparse matrices and take the result with slightly clever indexing and reshape it to 2x2xN.
But I doubt this will be faster than simple looping.