Alternate search functions to speed up code
5 次查看(过去 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 中查找有关 Performance and Memory 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!