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
This commit is contained in:
Jacques Lucke 2023-02-10 17:14:30 +01:00
parent 0ea15a6fbb
commit 923152d180
1 changed files with 141 additions and 103 deletions

View File

@ -28,12 +28,14 @@ static void copy_data_based_on_map(const Span<T> src,
const Span<int> index_map,
MutableSpan<T> 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<MEdge> src_edges = src_mesh.edges();
MutableSpan<MEdge> 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<MEdge> src_edges = src_mesh.edges();
MutableSpan<MEdge> 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<MPoly> dst_polys = dst_mesh.polys_for_write();
MutableSpan<MLoop> 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<MPoly> dst_polys = dst_mesh.polys_for_write();
MutableSpan<MLoop> 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<MPoly> dst_polys = dst_mesh.polys_for_write();
MutableSpan<MLoop> 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);
});
}
/**