From 923152d180178eaefb5d2ca57763af229fd77d6e Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 10 Feb 2023 17:14:30 +0100 Subject: [PATCH] Geometry Nodes: improve parallelization in Delete/Separate Geometry node This just adds `threading::parallel_for` and `threading::parallel_invoke` in a few places where it can be added trivially. The run time of the `separate_geometry` function changes from 830 ms to 413 ms in my test file. Pull Request #104563 --- .../nodes/node_geo_delete_geometry.cc | 244 ++++++++++-------- 1 file changed, 141 insertions(+), 103 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 912e846a3b9..5ed964c015e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -28,12 +28,14 @@ static void copy_data_based_on_map(const Span src, const Span index_map, MutableSpan dst) { - for (const int i_src : index_map.index_range()) { - const int i_dst = index_map[i_src]; - if (i_dst != -1) { - dst[i_dst] = src[i_src]; + threading::parallel_for(index_map.index_range(), 1024, [&](const IndexRange range) { + for (const int i_src : range) { + const int i_dst = index_map[i_src]; + if (i_dst != -1) { + dst[i_dst] = src[i_src]; + } } - } + }); } /** @@ -159,13 +161,15 @@ static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, const Span src_edges = src_mesh.edges(); MutableSpan dst_edges = dst_mesh.edges_for_write(); - for (const int i_src : IndexRange(src_mesh.totedge)) { - const int i_dst = edge_map[i_src]; - if (ELEM(i_dst, -1, -2)) { - continue; + threading::parallel_for(src_edges.index_range(), 1024, [&](const IndexRange range) { + for (const int i_src : range) { + const int i_dst = edge_map[i_src]; + if (ELEM(i_dst, -1, -2)) { + continue; + } + dst_edges[i_dst] = src_edges[i_src]; } - dst_edges[i_dst] = src_edges[i_src]; - } + }); } static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, @@ -178,18 +182,20 @@ static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, const Span src_edges = src_mesh.edges(); MutableSpan dst_edges = dst_mesh.edges_for_write(); - for (const int i_src : IndexRange(src_mesh.totedge)) { - const int i_dst = edge_map[i_src]; - if (i_dst == -1) { - continue; - } - const MEdge &e_src = src_edges[i_src]; - MEdge &e_dst = dst_edges[i_dst]; + threading::parallel_for(src_edges.index_range(), 1024, [&](const IndexRange range) { + for (const int i_src : range) { + const int i_dst = edge_map[i_src]; + if (i_dst == -1) { + continue; + } + const MEdge &e_src = src_edges[i_src]; + MEdge &e_dst = dst_edges[i_dst]; - e_dst = e_src; - e_dst.v1 = vertex_map[e_src.v1]; - e_dst.v2 = vertex_map[e_src.v2]; - } + e_dst = e_src; + e_dst.v1 = vertex_map[e_src.v1]; + e_dst.v2 = vertex_map[e_src.v2]; + } + }); } /* Faces and edges changed but vertices are the same. */ @@ -204,24 +210,26 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, MutableSpan dst_polys = dst_mesh.polys_for_write(); MutableSpan dst_loops = dst_mesh.loops_for_write(); - for (const int i_dst : masked_poly_indices.index_range()) { - const int i_src = masked_poly_indices[i_dst]; + threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { + for (const int i_dst : range) { + const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; - MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; + const MPoly &mp_src = src_polys[i_src]; + MPoly &mp_dst = dst_polys[i_dst]; + const int i_ml_src = mp_src.loopstart; + const int i_ml_dst = new_loop_starts[i_dst]; - const MLoop *ml_src = &src_loops[i_ml_src]; - MLoop *ml_dst = &dst_loops[i_ml_dst]; + const MLoop *ml_src = &src_loops[i_ml_src]; + MLoop *ml_dst = &dst_loops[i_ml_dst]; - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = ml_src[i].v; - ml_dst[i].e = edge_map[ml_src[i].e]; + mp_dst = mp_src; + mp_dst.loopstart = i_ml_dst; + for (int i : IndexRange(mp_src.totloop)) { + ml_dst[i].v = ml_src[i].v; + ml_dst[i].e = edge_map[ml_src[i].e]; + } } - } + }); } /* Only faces changed. */ @@ -235,24 +243,26 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, MutableSpan dst_polys = dst_mesh.polys_for_write(); MutableSpan dst_loops = dst_mesh.loops_for_write(); - for (const int i_dst : masked_poly_indices.index_range()) { - const int i_src = masked_poly_indices[i_dst]; + threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { + for (const int i_dst : range) { + const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; - MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; + const MPoly &mp_src = src_polys[i_src]; + MPoly &mp_dst = dst_polys[i_dst]; + const int i_ml_src = mp_src.loopstart; + const int i_ml_dst = new_loop_starts[i_dst]; - const MLoop *ml_src = &src_loops[i_ml_src]; - MLoop *ml_dst = &dst_loops[i_ml_dst]; + const MLoop *ml_src = &src_loops[i_ml_src]; + MLoop *ml_dst = &dst_loops[i_ml_dst]; - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = ml_src[i].v; - ml_dst[i].e = ml_src[i].e; + mp_dst = mp_src; + mp_dst.loopstart = i_ml_dst; + for (int i : IndexRange(mp_src.totloop)) { + ml_dst[i].v = ml_src[i].v; + ml_dst[i].e = ml_src[i].e; + } } - } + }); } static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, @@ -267,24 +277,26 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, MutableSpan dst_polys = dst_mesh.polys_for_write(); MutableSpan dst_loops = dst_mesh.loops_for_write(); - for (const int i_dst : masked_poly_indices.index_range()) { - const int i_src = masked_poly_indices[i_dst]; + threading::parallel_for(masked_poly_indices.index_range(), 512, [&](const IndexRange range) { + for (const int i_dst : range) { + const int i_src = masked_poly_indices[i_dst]; - const MPoly &mp_src = src_polys[i_src]; - MPoly &mp_dst = dst_polys[i_dst]; - const int i_ml_src = mp_src.loopstart; - const int i_ml_dst = new_loop_starts[i_dst]; + const MPoly &mp_src = src_polys[i_src]; + MPoly &mp_dst = dst_polys[i_dst]; + const int i_ml_src = mp_src.loopstart; + const int i_ml_dst = new_loop_starts[i_dst]; - const MLoop *ml_src = &src_loops[i_ml_src]; - MLoop *ml_dst = &dst_loops[i_ml_dst]; + const MLoop *ml_src = &src_loops[i_ml_src]; + MLoop *ml_dst = &dst_loops[i_ml_dst]; - mp_dst = mp_src; - mp_dst.loopstart = i_ml_dst; - for (int i : IndexRange(mp_src.totloop)) { - ml_dst[i].v = vertex_map[ml_src[i].v]; - ml_dst[i].e = edge_map[ml_src[i].e]; + mp_dst = mp_src; + mp_dst.loopstart = i_ml_dst; + for (int i : IndexRange(mp_src.totloop)) { + ml_dst[i].v = vertex_map[ml_src[i].v]; + ml_dst[i].e = edge_map[ml_src[i].e]; + } } - } + }); } static void delete_curves_selection(GeometrySet &geometry_set, @@ -574,16 +586,20 @@ static void compute_selected_mesh_data_from_vertex_selection_edge_face( int *r_selected_polys_num, int *r_selected_loops_num) { - - compute_selected_edges_from_vertex_selection( - mesh, vertex_selection, r_edge_map, r_selected_edges_num); - - compute_selected_polys_from_vertex_selection(mesh, - vertex_selection, - r_selected_poly_indices, - r_loop_starts, - r_selected_polys_num, - r_selected_loops_num); + threading::parallel_invoke( + mesh.totedge > 1000, + [&]() { + compute_selected_edges_from_vertex_selection( + mesh, vertex_selection, r_edge_map, r_selected_edges_num); + }, + [&]() { + compute_selected_polys_from_vertex_selection(mesh, + vertex_selection, + r_selected_poly_indices, + r_loop_starts, + r_selected_polys_num, + r_selected_loops_num); + }); } /** @@ -601,18 +617,24 @@ static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, int *r_selected_polys_num, int *r_selected_loops_num) { - compute_selected_verts_from_vertex_selection( - vertex_selection, r_vertex_map, r_selected_verts_num); - - compute_selected_edges_from_vertex_selection( - mesh, vertex_selection, r_edge_map, r_selected_edges_num); - - compute_selected_polys_from_vertex_selection(mesh, - vertex_selection, - r_selected_poly_indices, - r_loop_starts, - r_selected_polys_num, - r_selected_loops_num); + threading::parallel_invoke( + mesh.totedge > 1000, + [&]() { + compute_selected_verts_from_vertex_selection( + vertex_selection, r_vertex_map, r_selected_verts_num); + }, + [&]() { + compute_selected_edges_from_vertex_selection( + mesh, vertex_selection, r_edge_map, r_selected_edges_num); + }, + [&]() { + compute_selected_polys_from_vertex_selection(mesh, + vertex_selection, + r_selected_poly_indices, + r_loop_starts, + r_selected_polys_num, + r_selected_loops_num); + }); } /** @@ -629,14 +651,20 @@ static void compute_selected_mesh_data_from_edge_selection_edge_face( int *r_selected_polys_num, int *r_selected_loops_num) { - compute_selected_edges_from_edge_selection( - mesh, edge_selection, r_edge_map, r_selected_edges_num); - compute_selected_polys_from_edge_selection(mesh, - edge_selection, - r_selected_poly_indices, - r_loop_starts, - r_selected_polys_num, - r_selected_loops_num); + threading::parallel_invoke( + mesh.totedge > 1000, + [&]() { + compute_selected_edges_from_edge_selection( + mesh, edge_selection, r_edge_map, r_selected_edges_num); + }, + [&]() { + compute_selected_polys_from_edge_selection(mesh, + edge_selection, + r_selected_poly_indices, + r_loop_starts, + r_selected_polys_num, + r_selected_loops_num); + }); } /** @@ -654,15 +682,25 @@ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, int *r_selected_polys_num, int *r_selected_loops_num) { - r_vertex_map.fill(-1); - compute_selected_verts_and_edges_from_edge_selection( - mesh, edge_selection, r_vertex_map, r_edge_map, r_selected_verts_num, r_selected_edges_num); - compute_selected_polys_from_edge_selection(mesh, - edge_selection, - r_selected_poly_indices, - r_loop_starts, - r_selected_polys_num, - r_selected_loops_num); + threading::parallel_invoke( + mesh.totedge > 1000, + [&]() { + r_vertex_map.fill(-1); + compute_selected_verts_and_edges_from_edge_selection(mesh, + edge_selection, + r_vertex_map, + r_edge_map, + r_selected_verts_num, + r_selected_edges_num); + }, + [&]() { + compute_selected_polys_from_edge_selection(mesh, + edge_selection, + r_selected_poly_indices, + r_loop_starts, + r_selected_polys_num, + r_selected_loops_num); + }); } /**