0
votes

I have a probability matrix(glcm) of size 256x256x20. I have reshaped the matrix to 65536x20, so that I can eliminate one loop (along the 3rd dimension).

I want to do the following calculation.

for y = 1:256
    for x = 1:256
        if (ismember((x + y),(2:2*256))) 
            p_xplusy((x+y),:) = p_xplusy((x+y),:) + glcm(((y-1)*256+x),:);
        end
    end
end

So the p_xplusy will be a 511x20 matrix which each element is the sum of the diagonal of nxn sub matrix (where n belongs to 1:256) of the original 256x256x20 matrix.

This code block is making my program inefficient and I want to vectorize this loop. Any help would be appreciated.

2
ismember is a rather expensive function call. Just looking at this it looks like you could replace your if (ismember((x + y),(2:2*256))) line with if x+y<=2*256 && x+y>1. What I'm suggesting isn't vectorizing but it could speed this code up a LOT. - chessofnerd
Vectorisation is not necessarily faster in Matlab. With JIT compilation, for loops are often as fast as vectorised methods, and often scale better with less memory usage. Of course this assumes your for loop is sensibly-written, and @chessofnerd has already provided an improvement. - David
You said " p_xplusy will be a 511x20", but it threw me an error with it, assuming rand values. I had to make it rand(512,20) to make it work. Could you clarify on this? - Divakar

2 Answers

2
votes

Since your if statement is just checking whether x+y is less than or equal to 256, just force it to always be, and remove excess loops:

for y = 1:256
    for x = 1:256-y
        p_xplusy((x+y),:) = p_xplusy((x+y),:) + glcm(((y-1)*256+x),:);
    end
end

This should provide a noticeable speed-up to your code.

0
votes

You can reduce the complexity from O(n^2) to O(2*n) and thus improve runtime efficiency -

N = 256;
for k1 = 1:N
    idx_glcm = k1:N-1:N*(k1-1)+1;
    p_xplusy(k1+1,:) = p_xplusy(k1+1,:) + sum(glcm(idx_glcm,:),1);
end

for k1 = 2:N
    idx_glcm = k1*N:N-1:N*(N-1)+k1;
    p_xplusy(N+k1,:) = p_xplusy(N+k1,:) + sum(glcm(idx_glcm,:),1);
end

Some quick runtime tests seem to confirm our efficiency theory too.