简体   繁体   中英

How to speed-up this matlab loops

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 ?

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 ; ie 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.

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 ]);

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);

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:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM