how to make the .m code faster ?
2 views (last 30 days)
Show older comments
I wrote a matlab code but the execution time is more than 25 minutes . I think it is because the for loop and the index. so i have a matrix of data H(435*4258) , and i am trying to take vaulues from it depend on another values from another matrix. x,y have the same size (435*4258) like H and contain the location of the data in H . the output matrix has c(869*869) . what Iam trying to do is making a rectangle around every point and search for each point in the matrix data is in this range and take the average . can somebody help me to make it faster and less than 2 seconds. the code is like interpolation. is there any way to make it faster ? the code :
destance = 7.5;
d = distance/2;
m = 869;
n = 869;
rx = 3255;
c= zeros(m ,n);
newx = -rx:distance:+rx;
newy = -rx:distance:+rx;
for i = 1:m
yc = newy(i)+d;
yf = newy(i)-d;
for j = 1:n
xc = newx(j)+d;
xf = newx(j)-d;
ind = find(x>= xf & x<=xc & y >=yf & y<=yc);
if isempty(ind)
c(i,j) = NaN;
else
p = mean(h(ind));
c(i,j) = p;
end
end
end
3 Comments
Guillaume
on 3 Apr 2017
The code is bound to be slow. For each i, it rescans the x array which does not change between i for a given j. For each j, it rescans the y array which does not change for a given i. In other words, it performs m*n scans where only m+n scans are required at most.
Stephen23
on 4 Apr 2017
Accepted Answer
Guillaume
on 3 Apr 2017
Edited: Guillaume
on 4 Apr 2017
First, a piece of advice, don't hardcode values that matlab can easily calculate. In your code m and n are the number of elements in vectors newx and newy, so you shouldn't hardcode them. One day, you'll decide to change distance or rx and your program will fail because you'll forget to recalculate m and n. Much safer:
m = numel(newx);
n = numel(newy);
Anyway, if I understood correctly, this will produce the same result as your code:
distance = 7.5;
rx = 3255;
newx = -rx:distance:rx;
newy = -rx:distance:ry; %shouldn't there be a ry?
binx = discretize(x(:), newx - distance/2); %find index of x bin centered on newx with width distance
biny = discretize(y(:), newy - distance/2); %find index of y bin centered on newy with width distance
c = accumarray([biny, binx], h(:), [], @mean); %calculate the mean of all the values that fall within a bin
And should be much faster than your code which scan over and over the x and y arrays.
14 Comments
Guillaume
on 5 Apr 2017
Well use a loop then. More than 20% of your bins are NaN. That's a lot. as a result you're trying to do 303,426,761,910 hypot calculation at once, which is going to need a lot of memory.
[binycentres, binxcentres] = ndgrid((-rx:distance:rx) + distance/2);
for binidx = find(isnan(binmean))'
binidx
disttocentre = hypot(x(:) - binxcentres(binidx), y(:) - binycentres(binidx));
[~, nearestidx] = min(disttocentre);
binmean(binidx) = h(nearestidx);
end
That loop only does 1,852,230 hypot at once, but does it 163,817 times. You're trading speed for memory.
No matter what it's going to be very slow. You probably want to rethink what you're doing if you want to do this in real time.
More Answers (1)
Jan
on 3 Apr 2017
Edited: Jan
on 3 Apr 2017
I assume Guillaume's suggestion is faster. For a comparison thry this cleaned loop:
distance = 7.5; % Not "destance"
d = distance/2;
m = 869;
n = 869;
rx = 3255;
c = nan(m, n);
newx = -rx:distance:+rx;
newy = -rx:distance:+rx;
for i = 1:m
yc = newy(i) + d;
yf = newy(i) - d;
yi = (y >= yf & y <= yc); % Once per loop only
for j = 1:n
xc = newx(j) + d;
xf = newx(j) - d;
ind = (x >= xf & x <= xc & yi);
if any(ind)
c(i, j) = sum(h(ind)) / sum(ind);
end
end
end
@Jony Muller: Please run a TIC/TOC and post the results for the two methods. Thanks.
19 Comments
Jan
on 4 Apr 2017
@Jony: As long as you cannot provide input data, I cannot test some ideas I have. I understand that it is not trivial due to the file size. But this is your problem, so it is your turn to find a way to allow us to test suggestions and improvements.
But as far as I understand, Guillaume's code solves the problem already. Or does it reply something different from your code?
Guillaume
on 4 Apr 2017
@Jan,
I tested with this:
x = rx*(2*rand(435, 4258) - 1);
y = rx*(2*rand(435, 4258) - 1);
h = randi(200, 435, 4258);
which corresponds more or less to tony's description.
I don't know why the data is arrange in matrix form. As far as I understand this has no significance. The three variables could be just vectors.
See Also
Categories
Find more on Creating and Concatenating Matrices in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
