1

I hope you can help me out here, I have a speed problem in matlab with the following code:

%Example Definition
bf = 80;
sam = 10000;
dim = 300;
a = rand(bf, sam, dim);
T = rand(bf, sam, dim);
x = repmat(rand(1, sam, dim), [bf 1 1]);

%Calculation
E = zeros(size(T, ndims(T)));
dist = zeros(bf, sam);
a = repmat( a, [ 1 1 dim ]);
for i = 1:dim
    for j = 1:dim
        dist = x(:,:,j) .* T(:,:,i);
         E(i,j) = sum(sum(a(:,:,i) .* (0.5 * dist), 2), 1);
    end        
end

These 3 diminsional arrays are quite big (like 80x10000x300), so that there is a high computation time to calculate this 'E' matrix. I've already tried to vectorize it, but i have no a good idea how to do that without going into the memory limit (16 GB).

Any idea how to speed this up ?

yoshiii90
  • 15
  • 4
  • Could you make a small complete sample code by defining `T` `bf` `sam` `a` `dim` and `x`? – Yvon Mar 05 '17 at 20:11
  • Running loops will slow the computation. Convert formula into direct matrix operations and/or use parallel for loops. First one is preferred and viable as you've large data. Also consider data partitioning and processing in parallel loops (one for each partition). – SACn Mar 05 '17 at 20:40

4 Answers4

0

I don't see why it should be more than 16GB.

You store each pixel as 8B. 80*10K*300=240M, so each matrix is close to 2GB. You have for matrices, in total 8GB.

Your code is quite efficient, one simple suggestion to decrease memory usage is make everything single; i.e. single(zeros(size(T)))

Another suggestion is if you are using more matrices, clear variables when you are done.

Also, don't create dist variable, it is used only once.

smttsp
  • 4,011
  • 3
  • 33
  • 62
  • 1
    I tried to vectorize it with repmat and reshape. So I created the same values for 'X' times and run over the 16GB. Not with this code that i posted here :) – yoshiii90 Mar 05 '17 at 20:23
0

First of all, using i and j for loops slow things down. See: Using i and j as variables in Matlab

The out-of-memory problem occurs in a = repmat( a, [ 1 1 dim ]); which expands a by bf x sam x dim times. However the only place you access a is a(:,:,ii) and ii goes from 1 to dim. Therefore in the 300x300 elements in the 3rd dimension, only the first 300 are used.

One possible answer: You don't need to repmat and leave a as-is.

Another possible answer: a = repmat(rand(bf, sam, 1), [ 1 1 dim ]);

Community
  • 1
  • 1
Yvon
  • 2,903
  • 1
  • 14
  • 36
0

If you reshape 3D matrices to 2D matrices,nested loop will be converted to a matrix multiplication:

x = reshape(x,[],dim).';
a = reshape(a,[],dim);
T = reshape(T,[],dim);
E = x * (a.*T*.5);
rahnema1
  • 15,264
  • 3
  • 15
  • 27
0

Sometimes just updating your nested loop from the following

for i=1:m
    for j=1:n
        out(i,j) = something;
    end
end

to

for j=1:n
    for i=1:m
        out(i,j) = something;         %first rows fill
    end
end

would improve the performance significantly:

Developer
  • 8,258
  • 8
  • 49
  • 58