Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient method for finding elements in MATLAB matrix

I would like to know how can the bottleneck be treated in the given piece of code.

%% Points is an Nx3 matrix having the coordinates of N points where N ~ 10^6
Z = points(:,3)
listZ = (Z >= a & Z < b); % Bottleneck
np = sum(listZ); % For later usage
slice = points(listZ,:);

Currently for N ~ 10^6, np ~ 1000 and number of calls to this part of code = 1000, the bottleneck statement is taking around 10 seconds in total, which is a big chunk of time compared to the rest of my code.

Profiling Results

Some more screenshots of a sample code for only the indexing statement as requested by @EitanT

Profiling for sample codeProfiling for sample code

like image 506
OrangeRind Avatar asked Jun 20 '13 15:06

OrangeRind


People also ask

How do you extract an element from a matrix in MATLAB?

MATLAB extracts the matrix elements corresponding to the nonzero values of the logical array. The output is always in the form of a column vector. For example, A(A > 12) extracts all the elements of A that are greater than 12. Or you could replace all the spaces in a string matrix str with underscores.

How do I find the most frequent elements in an array in MATLAB?

M = mode( A ) returns the sample mode of A , which is the most frequently occurring value in A .

How do you find the specific element of a matrix?

The number of elements of a matrix = the number of rows multiplied by the number of columns. For example, if the number of rows is 3 and the number of columns is 4 in a matrix then the number of elements in it is 3 x 4 = 12.


3 Answers

If the equality on one side is not important you can reformulate it to a one-sided comparison and it gets one order of magnitude faster:

Z = rand(1e6,3);
a=0.5; b=0.6;
c=(a+b)/2;
d=abs(a-b)/2;
tic
for k=1:100,
    listZ1 = (Z >= a & Z < b); % Bottleneck
end
toc

tic
for k=1:100,
    listZ2 = (abs(Z-c)<d);
end
toc

isequal(listZ1, listZ2)

returns

Elapsed time is 5.567460 seconds.
Elapsed time is 0.625646 seconds.

ans =

     1
like image 200
Mohsen Nosratinia Avatar answered Oct 06 '22 18:10

Mohsen Nosratinia


Assuming the worst case:

  • element-wise & is not short-circuited internally
  • the comparisons are single-threaded

You're doing 2*1e6*1e3 = 2e9 comparisons in ~10 seconds. That's ~200 million comparisons per second (~200 MFLOPS).

Considering you can do some 1.7 GFLops on a single core, this indeed seems rather low.

Are you running Windows 7? If so, have you checked your power settings? You are on a mobile processor, so I expect that by default, there will be some low-power consumption scheme in effect. This allows windows to scale down the processing speed, so...check that.

Other than that....I really have no clue.

like image 25
Rody Oldenhuis Avatar answered Oct 06 '22 18:10

Rody Oldenhuis


Try doing something like this:

for i = 1:1000
    x = (a >= 0.5);
    x = (x < 0.6);
end

I found it to be faster than:

for i = 1:1000
    x = (a >= 0.5 & a < 0.6);
end

by about 4 seconds:

Elapsed time is 0.985001 seconds. (first one)
Elapsed time is 4.888243 seconds. (second one)

I think the reason for your slowing is the element wise & operation.

like image 26
James Mertz Avatar answered Oct 06 '22 20:10

James Mertz