I noticed something odd today. I have a matrix X
that is very skinny (20800 x 200
), double precision real numbers, not sparse, and I want the SVD of it quickly. Matlab does it rather fast:
> tic; [U,S,V] = svd(X,'econ'); toc
Elapsed time is 0.280848 seconds.
But if I ask for the SVD of its transpose, which is an extremely fat matrix, it is considerably slower.
> Xt = X';
> tic; [UU,SS,VV] = svd(Xt,'econ'); toc
Elapsed time is 0.722308 seconds.
Any ideas why this is? It seems quite odd, since if I wanted the SVD of a fat matrix, this means I can do it faster by taking the transpose, finding the SVD of this skinny matrix, and then swapping the "U"s and "V"s.
My guess is that it's because Matlab uses column major order, so in the skinny case, the "U" matrix is the large one and whatever routine that operates on it gets to use a stride-length of 1, whereas in the opposite case, the Matlab implementation calls something with a non-unit stride-length which is less efficient in terms of memory calls.
But even if there is a good reason, it begs the question, why doesn't Matlab check for fat matrices and just take the SVD of the transpose? The transpose operator is blazing fast. e.g.,
> tic; [VV,SS,UU] = svd(Xt','econ'); toc
Elapsed time is 0.293725 seconds.
gives me the same VV,UU,SS
as above, but much faster.
DGESVD
from LAPACK, which is based on the ideas of Gene Golub. The main thing is that is is implemented on matrices in Fortran, i.e. columwise storage. In this way processing values in the same colum is cheap and thats done in the implementation. Furthermore having a huge number of row, these operations take advantage out of the threading of the BLAS backend ( which is the MKL in the case of MATLAB). $\endgroup$