Vectorizing nested for loops
조회 수: 1 (최근 30일)
이전 댓글 표시
I have looked at other examples of vectorizing for loops, but I don't know how to apply those solutions to what I have.
Essentially, in this part of the code, I am randomly generating xyz coordinates for particles, and storing them in a coordinate array. I then want to calculate the distance, d, between particles. If this distance is less than a certain number based on the radius, R, and a constant, T, then I want to consider those particles in contact. I have a spanMatrix set up where a 1 indicates two particles are connected.
I am generating hundreds to thousands of particles, and this part of my code becomes very slow. Could anyone please help me speed this up? Thank you!
% Place an entry into a coordinate array with the random xyz coordinates
coordArray(numParticles,1) = x(1);
coordArray(numParticles,2) = y(1);
coordArray(numParticles,3) = z(1);
% For every element in the coordinate array
for i = 1:size(coordArray)
for j = 1:i
% for every (i,j) pair do distance calculation
d=(sqrt((coordArray(i,1)-coordArray(j,1)).^2 + (coordArray(i,2)-coordArray(j,2)).^2 + (coordArray(i,3)-coordArray(j,3)).^2));
% then check if the distance is close enough
if d <= (2*R + T)
% then these two span
spanMatrix(i,j) = 1;
spanMatrix(j,i) = 1;
end % end if d
end % end for j
end % end for i
댓글 수: 0
답변 (2개)
Guillaume
2019년 8월 30일
I am generating hundreds to thousands of particles
That's not many, it's only when you get in the order of a hundred thousand that the following starts to become problematic. The following generates a full symmetric matrix:
%coordArray: a Nx3 matrix
%generates a NxN full matrix of distance (using euclidean distance)
pointdist = sqrt(sum((permute(coordArray, [1, 3, 2]) - permute(coordArray, [3, 1, 2])) .^2, 3));
spanMatrix = pointdist <= 2*R + T;
A thousand points would only require around 8 MB of memory to store each full matrix pointdist and spanMatrix. Even 10,000 points is only around 800 MB. 100,000 points on the other hand requires around 75 GB. If you get to that number of points, then you can't vectorise the whole but can certainly vectorise the inner loop:
%coordArray: a Nx3 matrix
coordpairs = []; %to store coordinate pairs that will be used to construct the final sparse matrix
for ptidx = 1:size(coordpairs, 1)
pointdist = sqrt(sum((coordArray - coordArray(ptidx, :)) .^2, 2);
isclose = find(pointdist <= 2*R + T);
coordpairs = [coordpairs; [repmat(ptidx, numel(isclose), 1), isclose]]; %#ok<AGROW>
end
spanMatrix = sparse(coordpairs(:, 1), coordpairs(:, 2), 1)
Finally, note that in your original code:
for i = 1:size(coordArray)
works but most likely only by accident. Note that the size function returns a vector and that the colon operator only use the first element of the matrix. It's better to always be explicit:
for i = 1:size(coordArray, 1)
댓글 수: 0
darova
2019년 8월 30일
Use pdist2() to calculate combinations of distances
D = pdist2( ... )
cond = d <= (2*R + T); % indices of matrix you want
spanMatrix(cond) = 1;
참고 항목
카테고리
Help Center 및 File Exchange에서 Matrix Indexing에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!