ramgorur
ramgorur

Reputation: 2164

matlab: vectorizing a single loop that is ORing N binary matrices

The below code do some computation on a data matrix, the data is laid as --

data = [ ...
        1 2 3 4 5 6; ...
        1 2 3 4 5 6; ...
        1 2 3 4 5 6;] 

and the code that I am running is like this --

[~,col] = size(data) ;
flag1 = bsxfun(@lt, data(:,1), data(:,1).'); 
flag2 = bsxfun(@gt, data(:,1), data(:,1).'); 

for cindex = 2:col % can we get rid of this loop ?
    flag1 = flag1 | bsxfun(@lt, data(:,cindex), data(:,cindex).');
    flag2 = flag2 | bsxfun(@gt, data(:,cindex), data(:,cindex).');
end

what this code is doing is comparing each row in column major order and creating two matrices of binary values flag1 and flag2.

Is there anyway to get rid of this for cindex = 2:col loop ?

Upvotes: 2

Views: 70

Answers (2)

ramgorur
ramgorur

Reputation: 2164

I was curious to see, how much gain I am actually getting, it's actually a double speedup! here is a benchmark --

clear all 

data = rand(500,500);
[~,col] = size(data);
maxrun = 20 ;

%warm up
for k = 1:50000
    tic(); elapsed = toc();
end

toctime = 0 ;
for i = 1:maxrun
    flag1 = bsxfun(@lt, data(:,1), data(:,1).'); 
    flag2 = bsxfun(@gt, data(:,1), data(:,1).'); 
    tic
    for cindex = 2:col % can we get rid of this loop ?
        flag1 = flag1 | bsxfun(@lt, data(:,cindex), data(:,cindex).');
        flag2 = flag2 | bsxfun(@gt, data(:,cindex), data(:,cindex).');
    end
    toctime = toctime + toc ;
end
fprintf('time elapsed: %0.4f sec\n', toctime/maxrun);

toctime = 0 ;
for i = 1:maxrun
    flag1 = bsxfun(@lt, data(:,1), data(:,1).'); 
    flag2 = bsxfun(@gt, data(:,1), data(:,1).'); 
    tic
    for cindex = 2:col % can we get rid of this loop ?
        flag1 = bsxfun(@or, flag1, bsxfun(@lt, data(:,cindex), data(:,cindex).'));
        flag2 = bsxfun(@or, flag2, bsxfun(@gt, data(:,cindex), data(:,cindex).'));
    end
    toctime = toctime + toc ;
end
fprintf('time elapsed: %0.4f sec\n', toctime/maxrun);

toctime = 0 ;
for i = 1:maxrun
    tic
    flag1 = any(bsxfun(@lt,permute(data,[1 3 2]),permute(data,[3 1 2])),3);
    flag2 = any(bsxfun(@gt,permute(data,[1 3 2]),permute(data,[3 1 2])),3);
    toctime = toctime + toc ;
end
fprintf('time elapsed: %0.4f sec\n', toctime/maxrun);

fprintf('done.\n');

one interesting thing to note doing | over two matrices and doing bsxfun(@or... are almost same --

>> vectest
time elapsed: 0.8609 sec
time elapsed: 0.7914 sec
time elapsed: 0.3285 sec
done.

Upvotes: 1

Divakar
Divakar

Reputation: 221574

You need some permuting(rearrange dimensions) to create singleton dimensions so that expansions would take place when using bsxfun later on, which would essentially replace the looping as used in the original posted code. So, the implementation would look something like this -

flag1 = any(bsxfun(@lt,permute(data,[1 3 2]),permute(data,[3 1 2])),3);
flag2 = any(bsxfun(@gt,permute(data,[1 3 2]),permute(data,[3 1 2])),3);

Upvotes: 2

Related Questions