-3

I'm impressed by the low speed of Matlab matrix arithmetic operation in my code as follows:

pitemp=zeros(nz,na,nb,nk,nxi,nann,nbn,nkn);

 pitemp=alphal^(alphal*alphares)*alpham^(alpham*alphares)*expz.^alphares.*expk.^((eta-alphal-alpham)*alphares)+(1-delta)*expk-expkn...
-ximgrid.*(expkn./expk-1+delta>zeta | expkn./expk-1+delta<-zeta)+rd*amgrid-rl*bmgrid-amgridn+bmgridn;

pitemp, expz, expk, expkn, amgrid,bmgrid, amgridn, bmgridn are all 8*D matrix. It seems that it's not the logical operator part that slower things down. I just don't see any clue why it could take up 10 seconds.... Does any one see where the problem is? Thanks a lot in advance! I'm really being killed by the slow performance just because of this line...

Woodpecker
  • 17
  • 3
  • It could easily be a very big matrix with so many dimensions, even if each dimension was relatively small. What values for `nz,na,nb,nk,nxi,nann,nbn,nkn` are you using when the operation takes 10 seconds? – Neil Slater Jul 27 '15 at 22:07
  • Have you tried the profiler? And how many elements are in the matrices? – rlbond Jul 27 '15 at 22:08
  • @NeilSlater nz=10,na=10,nb=10,nk=10,nxi=5,nann=10,nabn=10,nkn=10 Is it true even in arithmetic operation, the speed could slow down so much with higher n's? – Woodpecker Jul 27 '15 at 22:18
  • 4
    Your array has 50 million elements... – sco1 Jul 27 '15 at 22:21
  • 1
    well considering your matrix is 50000000 elements, or about 400MB of RAM, that is pretty darn big. 10 seconds seems reasonable to me. And also what is the point in you preallocating memory when you are just overwriting it with your second line. I would also like to add that in this case, putting everything into one line of code is bad. It makes it highly unreadable and very hard to debug. – MZimmerman6 Jul 27 '15 at 22:23
  • 2
    Get rid of unnecessary operations to improve the performance. In `(expkn./expk-1+delta>zeta | expkn./expk-1+delta<-zeta)` you are calculating the same operations twice. – Daniel Jul 27 '15 at 22:34
  • 1
    10 seconds for `5e7` elements is very reasonable. The size of your input also matters in your timing. If you tried this on a moderately small sized matrix, then you'll see that it's faster. Other than what Daniel said about the redundant calculations, you're pretty much [SOL](http://www.urbandictionary.com/define.php?term=SOL) to try and make this faster. – rayryeng Jul 27 '15 at 22:36
  • @NeilSlater - Come visit us in our MATLAB room from time to time to say hello :) http://chat.stackoverflow.com/rooms/81987/matlab-and-octave – rayryeng Jul 27 '15 at 22:37
  • @excaza - Come visit us in our MATLAB room from time to time to say hello :) http://chat.stackoverflow.com/rooms/81987/matlab-and-octave – rayryeng Jul 27 '15 at 22:37
  • @MZimmerman6 - Come visit us in our MATLAB room from time to time to say hello :) http://chat.stackoverflow.com/rooms/81987/matlab-and-octave – rayryeng Jul 27 '15 at 22:38
  • @rayryeng How about using Fortran to calculate this part instead? – Woodpecker Jul 28 '15 at 01:17
  • @Woodpecker probably no difference. – rayryeng Jul 28 '15 at 02:13
  • @rayryeng A high number of dimesions can indeed take a lot of extra time. See my answer. – patrik Jul 28 '15 at 09:12

1 Answers1

2

High dimensional matrices may indeed be slow to work with sometimes. I will show this comparing the speed of a 2D matrix and your matrix. The matrices will have approximately the same size.

m = function fRef1()
    m = rand(5000,10000); % Generate an unsorted matrix to ensure worst case behaviour
end

Running the timeit function,

timeit(@fRef1,1) 

The matrix generation takes 0.7058s for the 2D matrix

m = function fRef2()
    m=rand(10,10,10,10,5,10,10,10);
end

timeit(fRef2,1)

And for the 8D matrix it takes 0.7277s which is about the same speed.

Now test to do a simple matrix operation

function M = f1()
    m = rand(5000,10000);
    M = m.^2.*m+m;
end

Which with timeit takes 0.9449s. Using the result from fRef1 you can see the matrix operation takes about 0.24s.

Now compare to the 8D matrix

function M = f2()
    m = rand(10,10,10,10,5,10,10,10);
    M = m.^2.*m+m;
end

which with timeit takes 1.2553s. Removing the time from fRef2 you will get the time for the matrix operation. The calculation time is then 0.5276s which is about twize the time for the 2D matrix. So can we do better? The answer is yes! Since the operations are done elementwise, the operation is independent on the shape of the matrix. Let us then modify the matrix to a for that Matlab finds more suitable.

function M=f3()
    m=rand(10,10,10,10,5,10,10,10);
    m=m(:); % Create a row vector
    M=m.^2.*m+m;
    M = reshape(M,10,10,10,10,5,10,10,10); % reshape the matrix again to
                                           % its original shape
end

timeit gives us a result of 0.9494s. Which, by removing the time for the creation of m gives us a result of 0.2217s which is about the same time as of the 2D matrix.

Windows 7, intel core i5-2540M, 2.60GHz, Matlab 2014b

patrik
  • 4,506
  • 6
  • 24
  • 48