One step reduction in MATLAB increases the execution time - matlab

I am doing a comparison and performance test of 3 methods to get the closest index of what i click in the ginput() the first method takes distance from each click and finds the nearest index in the next step the second one is doing the same but through a for loop and 3rd is the exact same copy of the first one but reduction of one step
ax = subplot(1,1,1)
plot(timestamps,datavalue)
hzoom = zoom(ax);
hzoom.Motion = 'horizontal';
[x, ~] = ginput(2);
%1)
tic;
tmp = abs(bsxfun(#minus,x,datenum(timestamps).'));
[~, idx1] = min(tmp,[],2);
toc;
%2)
tic;
for r = 1:length(x)
val = x(r);
tmp = abs(datenum(datenum(timestamps - val)));
[~, idx2] = min(tmp);
closest_indx(r) = idx2;
end
toc;
%3)
tic;
[~, idx3] = min(abs(bsxfun(#minus,x,datenum(timestamps).')),[],2);
toc;
Now when I look at the results
test1)
Elapsed time is 0.009182 seconds.
Elapsed time is 0.019211 seconds.
Elapsed time is 0.011261 seconds.
test2)
Elapsed time is 0.012625 seconds.
Elapsed time is 0.022681 seconds.
Elapsed time is 0.017999 seconds.
test3)
Elapsed time is 0.013053 seconds.
Elapsed time is 0.020170 seconds.
Elapsed time is 0.015248 seconds.
test4)
Elapsed time is 0.011613 seconds.
Elapsed time is 0.018644 seconds.
Elapsed time is 0.015952 seconds.
It takes less time for the first method even though it has one more step of taking all the values and placing in into a 'tmp' matrix. Does anyone have a good explaination for this ?

Related

How to decrease the computation time of this code?

I am working on computing some features of an image data set and saving the features for later use. Below is the code:
tic
l = 9907 % size of image data set
% pre-allocating space for variables in the for loop
Icolor = cell(1,l);
Iwave = cell(1,l);
IglrlFeatures = cell(1,l);
for i = 1:l % l = size of image data set = 9907
IDB{1,i} = imread(strcat(path,strcat(num2str(i),'.jpg')));
Icolor{1,i} = colorMoments(IDB{1,i}); % 6-features in each cell
Iwave{1,i} = waveletTransform(IDB{1,i}); % 8-features in each cell
IglrlFeatures{1,i} = textureFeatures(IDB{1,i}); % 44-features in each cell
ICW{1,i} = [Icolor{1,i} Iwave{1,i} IglrlFeatures{1,i}];
end
toc
Here the computation time for each function on single image is:
colorMoments(single_image) = Elapsed time is 0.009689 seconds.
waveletTransform(single_image) = Elapsed time is 0.018069 seconds.
textureFeatures(single_image) = Elapsed time is 0.022902 seconds.
l = data set size = 9907 images
Computational times for different data set sizes (l):
l = 10; Elapsed time is 0.402629 seconds.
l = 100; Elapsed time is 2.233971 seconds.
l = 1000; Elapsed time is 21.178395 seconds.
l = 2000; Elapsed time is 44.510071 seconds.
l = 5000; Elapsed time is 111.393866 seconds.
l = 9907; Elapsed time is 238.924998 seconds. approximately (~4 mins)
I want to decrease this computational time, any suggestions?
Thanks,
Gopi
The measured times seem to indicate computational complexity of order O(n). I doubt that the order can be reduced further for this type of problem. So, I believe that, at best, we can only hope for a linear increase in performance.
One thing you should look into is whether the code is using multiple processor cores. If not, try restructuring the for-loop to be able to use parfor instead.

Faster version of length(find()) for selecting elements from some range from vectors (MATLAB)

I have 1Xn cell array of values. and I want to count values that are in given range in matlab.
I implemented it as follows :
count1 = length(find(h{1}<ti & h{1}>ti-INT));
h is my cell array and I want the count of values between ti and ti-INT.
This implementation give correct result, but it is very slow.
Is there any faster function available for the specified operation ?
Sum the occurrence flags:
count1 = sum(h{1}<ti & h{1}>ti-INT);
I know that I will upset the Gods of MATLAB for using tic and toc for code timig, but:
x = rand(10^7,1);
tic; sum(x>0.5); toc;
tic; nnz(x>0.5); toc;
tic; length(find(x>0.5)); toc;
shows on several runs that sum() is twice as fast as nnz(), and 3 times faster than length(find()), e.g.:
Elapsed time is 0.049855 seconds.
Elapsed time is 0.120931 seconds.
Elapsed time is 0.162025 seconds.
This is on my R2012a running on a Windows machine with i5 + 3Gb RAM.
Later edit:
For counting the elements from the entire cell array, one may use:
count_all = sum(cellfun(#(x) sum(x<ti & x>ti-INT), h));

MATLAB: datetime and etime

I need to use etime to calculate how many seconds a computation takes. I thought about something like this:
t1 = datetime('now');
% Do some computation
t2 = datetime('now');
temp = etime(t2, t1)
But I am getting this error message:
Error using etime(line 40), Index exceeds matrix dimensions.
What's wrong with it?
The inputs to etime are expected to be vectors that are the same format as the output of clock and not datetime objects.
t1 = clock;
t2 = clock;
elapsed = etime(t2, t1)
It is likely easier to surround your code with tic and toc which will automatically compute the elapsed time.
tmr = tic;
% do stuff
elapsed = toc(tmr);
That being said, if you want an accurate measurement of execution time, it is far better to use timeit.

Octave/Matlab: Adding new elements to a vector

Having a vector x and I have to add an element (newElem) .
Is there any difference between -
x(end+1) = newElem;
and
x = [x newElem];
?
x(end+1) = newElem is a bit more robust.
x = [x newElem] will only work if x is a row-vector, if it is a column vector x = [x; newElem] should be used. x(end+1) = newElem, however, works for both row- and column-vectors.
In general though, growing vectors should be avoided. If you do this a lot, it might bring your code down to a crawl. Think about it: growing an array involves allocating new space, copying everything over, adding the new element, and cleaning up the old mess...Quite a waste of time if you knew the correct size beforehand :)
Just to add to #ThijsW's answer, there is a significant speed advantage to the first method over the concatenation method:
big = 1e5;
tic;
x = rand(big,1);
toc
x = zeros(big,1);
tic;
for ii = 1:big
x(ii) = rand;
end
toc
x = [];
tic;
for ii = 1:big
x(end+1) = rand;
end;
toc
x = [];
tic;
for ii = 1:big
x = [x rand];
end;
toc
Elapsed time is 0.004611 seconds.
Elapsed time is 0.016448 seconds.
Elapsed time is 0.034107 seconds.
Elapsed time is 12.341434 seconds.
I got these times running in 2012b however when I ran the same code on the same computer in matlab 2010a I get
Elapsed time is 0.003044 seconds.
Elapsed time is 0.009947 seconds.
Elapsed time is 12.013875 seconds.
Elapsed time is 12.165593 seconds.
So I guess the speed advantage only applies to more recent versions of Matlab
As mentioned before, the use of x(end+1) = newElem has the advantage that it allows you to concatenate your vector with a scalar, regardless of whether your vector is transposed or not. Therefore it is more robust for adding scalars.
However, what should not be forgotten is that x = [x newElem] will also work when you try to add multiple elements at once. Furthermore, this generalizes a bit more naturally to the case where you want to concatenate matrices. M = [M M1 M2 M3]
All in all, if you want a solution that allows you to concatenate your existing vector x with newElem that may or may not be a scalar, this should do the trick:
x(end+(1:numel(newElem)))=newElem

Matlab's FOR loop iteration time increases

I'm trying to span values of a certain multivariable function f(nu,delta,Omega,kappa,Gamma). The code is as follows:
% PREALLOCATE RESULT MATRIX
N = 10;
d = 0.1;
M = zeros(4*N/d+(2*N+1)/d,6);
% SET UP LOOP INDICES
i=1;
increm=1;
% LOOP OVER MULTIPLE VARIABLE
for nu=d:d:N
for delta=-N:d:N
for Omega=d:d:N
for kappa=d:d:N
tic
for Gamma=d:d:N
% CALCULATE THE FUNCTION
mss = ((Gamma+kappa).*((Gamma+kappa).^2+4.*(delta+(-1).*nu).^2).^(-1)+( ...
-1).*(Gamma+kappa).*((Gamma+kappa).^2+4.*(delta+nu).^2).^(-1)+( ...
kappa.^2+4.*(delta+(-1).*nu).^2).^(-1).*(((2.*Gamma+kappa).^2+4.*( ...
delta+(-1).*nu).^2).*(kappa.*(Gamma+kappa).*(2.*Gamma+kappa)+4.*(( ...
-1).*Gamma+kappa).*(delta+(-1).*nu).^2)+4.*(kappa.*(2.*Gamma+ ...
kappa).^2+4.*(4.*Gamma+kappa).*(delta+(-1).*nu).^2).*Omega.^2).*( ...
16.*(delta+(-1).*nu).^4+4.*(delta+(-1).*nu).^2.*((Gamma+kappa).^2+ ...
(2.*Gamma+kappa).^2+(-8).*Omega.^2)+((Gamma+kappa).*(2.*Gamma+ ...
kappa)+4.*Omega.^2).^2).^(-1)+(-1).*(kappa.^2+4.*(delta+nu).^2).^( ...
-1).*(((2.*Gamma+kappa).^2+4.*(delta+nu).^2).*(kappa.*(Gamma+ ...
kappa).*(2.*Gamma+kappa)+4.*((-1).*Gamma+kappa).*(delta+nu).^2)+ ...
4.*(kappa.*(2.*Gamma+kappa).^2+4.*(4.*Gamma+kappa).*(delta+nu).^2) ...
.*Omega.^2).*(16.*(delta+nu).^4+4.*(delta+nu).^2.*((Gamma+kappa) ...
.^2+(2.*Gamma+kappa).^2+(-8).*Omega.^2)+((Gamma+kappa).*(2.*Gamma+ ...
kappa)+4.*Omega.^2).^2).^(-1)).^(-1).*((Gamma+kappa).*((Gamma+ ...
kappa).^2+4.*(delta+nu).^2).^(-1)+(kappa.^2+4.*(delta+nu).^2).^( ...
-1).*(((2.*Gamma+kappa).^2+4.*(delta+nu).^2).*(kappa.*(Gamma+ ...
kappa).*(2.*Gamma+kappa)+4.*((-1).*Gamma+kappa).*(delta+nu).^2)+ ...
4.*(kappa.*(2.*Gamma+kappa).^2+4.*(4.*Gamma+kappa).*(delta+nu).^2) ...
.*Omega.^2).*(16.*(delta+nu).^4+4.*(delta+nu).^2.*((Gamma+kappa) ...
.^2+(2.*Gamma+kappa).^2+(-8).*Omega.^2)+((Gamma+kappa).*(2.*Gamma+ ...
kappa)+4.*Omega.^2).^2).^(-1));
% STORE THE RESULT
M(i,:) = [mss nu delta Omega kappa Gamma];
i = i+increm;
end
end
toc
end
end
end
save M
However the preallocation does not help that each iteration takes longer time. When I run the code and interrupt it prematurely, the iterations take
Elapsed time is 0.003354 seconds.
Elapsed time is 0.006374 seconds.
Elapsed time is 0.009043 seconds.
Elapsed time is 0.012092 seconds.
Elapsed time is 0.015287 seconds.
Elapsed time is 0.019239 seconds.
Elapsed time is 0.023898 seconds.
Elapsed time is 0.035345 seconds.
Elapsed time is 0.046675 seconds.
Elapsed time is 0.056000 seconds.
Elapsed time is 0.066323 seconds.
Elapsed time is 0.072178 seconds.
Elapsed time is 0.075174 seconds.
Elapsed time is 0.081095 seconds.
Elapsed time is 0.095016 seconds.
Elapsed time is 0.095214 seconds.
Elapsed time is 0.100089 seconds.
Elapsed time is 0.104286 seconds.
Elapsed time is 0.109454 seconds.
Elapsed time is 0.115368 seconds.
Elapsed time is 0.124278 seconds.
Elapsed time is 0.131521 seconds.
Elapsed time is 0.135023 seconds.
Elapsed time is 0.137370 seconds.
Elapsed time is 0.145331 seconds.
Elapsed time is 0.163449 seconds.
Elapsed time is 0.162654 seconds.
Elapsed time is 0.159628 seconds.
Elapsed time is 0.166585 seconds.
I don't see how the change of variables itself could cause this, because the only vary by amount d, which shouldn't make it much harder to calculate the new value of mss than in the previous interation.
You aren't pre-allocating a big enough array!
If you do the following nested loop
for ii=1:3
for jj = 1:4
doSomething()
end
end
doSomething is executed 3*4=12 times. With your allocation scheme, you would be allocating 3+4=7 times.
In other words, change your preallocation to
M = zeros((N/d)^4*(2*N+1)/d,6);
and all will be fine.