how to make the .m code faster ?

2 次查看(过去 30 天)
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 个评论
Guillaume
Guillaume 2017-4-3
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.

请先登录,再进行评论。

采纳的回答

Guillaume
Guillaume 2017-4-3
编辑:Guillaume 2017-4-4
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 个评论
Jony Muller
Jony Muller 2017-4-5
Error using bsxfun Requested 1852230x163817 (2260.7GB) array exceeds maximum array size preference. Creation of arrays greater than this limit may take a long time and cause MATLAB to become unresponsive. See array size limit or preference panel for more information.
Guillaume
Guillaume 2017-4-5
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.

请先登录,再进行评论。

更多回答(1 个)

Jan
Jan 2017-4-3
编辑:Jan 2017-4-3
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 个评论
Jan
Jan 2017-4-4
@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
Guillaume 2017-4-4
@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.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Creating and Concatenating Matrices 的更多信息

标签

尚未输入任何标签。

产品

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by