Alternate search functions to speed up code
조회 수: 3 (최근 30일)
이전 댓글 표시
I have tried profiling my code and apparently it is very slow to the use of the desarchn algorithm.
The whole program intital takes around 400 seconds to run with this one function shown below being the bottle neck taking 350 seconds. In particular, the dsearchn function takes a very long time. What can I do to make it run faster?
Other things I have tried
- I tried implementing the desarchn function but, the code took signficiantly longer to run (even) 1000 seconds the function had to finish exectuing)
- I tried using parfor loops but, MATLAB gives me an error saying that the code cannot use parfor due to the loop structures.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function connectivity_coords = mapcoordinates(num_voxels, sz, vox_x_dim, vox_y_dim, vox_z_dim, node_list_matrix,index, corner_coords, counter, connectivity_coords)
for ind = 1:num_voxels
% Convert voxel index to subscripts
[x, y, z] = ind2sub(sz, ind);
%reset the origin to zero
x= (x-1)*vox_x_dim;
y =(y-1)*vox_y_dim;
z=(z-1)*vox_z_dim;
% Calculate the coordinates of the cube corners
corners = [
x, y, z %4;
x+vox_x_dim, y, z %3;
x+vox_x_dim, y+vox_y_dim, z %2
x, y+vox_y_dim, z %1;
x, y, z+vox_z_dim %8
x+vox_x_dim, y, z+vox_z_dim %7;
x+vox_x_dim, y+vox_y_dim, z+vox_z_dim %6;
x, y+vox_y_dim, z+vox_z_dim %5;
];
smallindex = dsearchn(node_list_matrix(:,2:4), corners(1:end,1:3));
index = [index;smallindex];
start = ind*8-7;
% Assign the element set
connectivity = [
index(start);
index(start+1);
index(start+2);
index(start+3);
index(start+4);
index(start+5);
index(start+6);
index(start+7);
];
% Store the corner coordinates in the array
corner_coords((ind-1)*8 + 1 : ind*8, :) = corners;
% Store the connectivity information
if counter<= num_voxels
connectivity_coords(counter,1:8) = connectivity;
end
counter=counter+1;
end
end
댓글 수: 1
Les Beckham
2023년 9월 18일
If you provide all of the variable values and the command that you used to call the function so that people can test, you will be more likely to get an answer.
load('variables.mat');
whos
coords = mapcoordinates(num_voxels, sz, vox_x_dim, vox_y_dim, vox_z_dim, node_list_matrix,index, corner_coords, counter, connectivity_coords);
function connectivity_coords = mapcoordinates(num_voxels, sz, vox_x_dim, vox_y_dim, vox_z_dim, node_list_matrix,index, corner_coords, counter, connectivity_coords)
for ind = 1:num_voxels
% Convert voxel index to subscripts
[x, y, z] = ind2sub(sz, ind);
%reset the origin to zero
x= (x-1)*vox_x_dim;
y =(y-1)*vox_y_dim;
z=(z-1)*vox_z_dim;
% Calculate the coordinates of the cube corners
corners = [
x, y, z %4;
x+vox_x_dim, y, z %3;
x+vox_x_dim, y+vox_y_dim, z %2
x, y+vox_y_dim, z %1;
x, y, z+vox_z_dim %8
x+vox_x_dim, y, z+vox_z_dim %7;
x+vox_x_dim, y+vox_y_dim, z+vox_z_dim %6;
x, y+vox_y_dim, z+vox_z_dim %5;
];
smallindex = dsearchn(node_list_matrix(:,2:4), corners(1:end,1:3));
index = [index;smallindex];
start = ind*8-7;
% Assign the element set
connectivity = [
index(start);
index(start+1);
index(start+2);
index(start+3);
index(start+4);
index(start+5);
index(start+6);
index(start+7);
];
% Store the corner coordinates in the array
corner_coords((ind-1)*8 + 1 : ind*8, :) = corners;
% Store the connectivity information
if counter<= num_voxels
connectivity_coords(counter,1:8) = connectivity;
end
counter=counter+1;
end
end
채택된 답변
Bruno Luong
2023년 9월 19일
편집: Bruno Luong
2023년 9월 19일
The below code takes
% Elapsed time is 48.221007 seconds.
on my PC.
Improvement are:
- use delaunayTriangulation instead of dsearchn
- vectorize the for loop in order to call nearestNeighbor only once
- agregate vortex corners in case there are duplication
load('variables.mat')
sz = [floor(no_vox_x), floor(no_vox_y), floor(no_vox_z)];
num_voxels = prod(sz);
% Fix missing parameters not given by OP
connectivity_coords = [];
dxyz=max(node_list_matrix(:,2:4),[],1)./sz;
vox_x_dim = dxyz(1);
vox_y_dim = dxyz(2);
vox_z_dim = dxyz(3);
% Code starts here
ind = 1:num_voxels;
[x, y, z] = ind2sub(sz, ind);
x = (x-1)*vox_x_dim;
y = (y-1)*vox_y_dim;
z = (z-1)*vox_z_dim;
[xc,yc,zc] = ndgrid([0 vox_x_dim], [0 vox_y_dim], [0 vox_z_dim]);
cube = [xc(:) yc(:) zc(:)];
cube = cube([1 2 4 3 5 6 8 7],:);
tic
cube = reshape(cube, [8 1 3]);
xyz = reshape([x(:) y(:) z(:)], 1, [], 3);
corners = xyz + cube;
corners = reshape(corners, [], 3);
[ucorners,~,J] = uniquetol(corners, 'ByRows', 1);
DT = delaunayTriangulation(node_list_matrix(:,2:4));
ID = nearestNeighbor(DT,ucorners);
smallindex = ID(J);
smallindex = reshape(smallindex, [8 num_voxels]);
toc
%check matching of the 1000th data
smallindex1000 = dsearchn(node_list_matrix(:,2:4), corners(999*8+(1:8),:));
smallindex1000
smallindex(:,1000)
isequal(smallindex1000, smallindex(:,1000))
index = smallindex.';
h = size(connectivity_coords,1);
connectivity_coords = [connectivity_coords; index(1:min(num_voxels-h,end),:)];
댓글 수: 2
Bruno Luong
2023년 10월 9일
IMO there is no obvious way to run delaunayTriangulation in parallel.
But you can ask this question to another thread so that other person can see. if they know how to accelerate it
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 Logical에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!