BLI: add use_threading parameter to parallel_invoke

`parallel_invoke` allows executing functions on separate threads.
However, creating tasks in tbb has a measurable amount of overhead.
Therefore, it can be benefitial to disable parallelization when
the amount of work done per function is small.

See D15539 for some benchmark results.

Differential Revision: https://developer.blender.org/D15539
This commit is contained in:
Iliay Katueshenock 2022-07-26 11:06:49 +02:00 committed by Jacques Lucke
parent 203e7ba332
commit c94ca54cda
7 changed files with 25 additions and 0 deletions

View File

@ -1165,6 +1165,7 @@ static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves,
CurvesGeometry new_curves{new_point_count, new_curve_count};
threading::parallel_invoke(
256 < new_point_count * new_curve_count,
/* Initialize curve offsets. */
[&]() { new_curves.offsets_for_write().copy_from(new_curve_offsets); },
[&]() {
@ -1237,6 +1238,7 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
CurvesGeometry new_curves{new_tot_points, new_tot_curves};
threading::parallel_invoke(
256 < new_tot_points * new_tot_curves,
/* Initialize curve offsets. */
[&]() {
MutableSpan<int> new_offsets = new_curves.offsets_for_write();

View File

@ -105,6 +105,22 @@ template<typename... Functions> void parallel_invoke(Functions &&...functions)
#endif
}
/**
* Same #parallel_invoke, but allows disabling threading dynamically. This is useful because when
* the individual functions do very little work, there is a lot of overhead from starting parallel
* tasks.
*/
template<typename... Functions>
void parallel_invoke(const bool use_threading, Functions &&...functions)
{
if (use_threading) {
parallel_invoke(std::forward<Functions>(functions)...);
}
else {
(functions(), ...);
}
}
/** See #BLI_task_isolate for a description of what isolating a task means. */
template<typename Function> void isolate_task(const Function &function)
{

View File

@ -188,6 +188,7 @@ struct DensityAddOperationExecutor {
* curves. */
Array<bool> new_curve_skipped(new_positions_cu.size(), false);
threading::parallel_invoke(
512 < already_added_curves + new_positions_cu.size(),
/* Build kdtree from root points created by the current stroke. */
[&]() {
for (const int i : IndexRange(already_added_curves)) {
@ -309,6 +310,7 @@ struct DensityAddOperationExecutor {
};
threading::parallel_invoke(
1024 < original_positions.size() + deformed_positions.size(),
[&]() {
self_->original_curve_roots_kdtree_ = roots_kdtree_from_positions(original_positions);
},

View File

@ -734,6 +734,8 @@ static void select_grow_invoke_per_curve(Curves &curves_id,
}
threading::parallel_invoke(
1024 < curve_op_data.selected_point_indices.size() +
curve_op_data.unselected_point_indices.size(),
[&]() {
/* Build KD-tree for the selected points. */
KDTree_3d *kdtree = BLI_kdtree_3d_new(curve_op_data.selected_point_indices.size());

View File

@ -60,6 +60,7 @@ static void deform_curves(const CurvesGeometry &curves,
Array<ReverseUVSampler::Result> surface_samples_old(curves_num);
Array<ReverseUVSampler::Result> surface_samples_new(curves_num);
threading::parallel_invoke(
1024 < curves_num,
[&]() { reverse_uv_sampler_old.sample_many(curve_attachment_uvs, surface_samples_old); },
[&]() { reverse_uv_sampler_new.sample_many(curve_attachment_uvs, surface_samples_new); });

View File

@ -183,6 +183,7 @@ Mesh *create_line_mesh(const float3 start, const float3 delta, const int count)
MutableSpan<MEdge> edges{mesh->medge, mesh->totedge};
threading::parallel_invoke(
1024 < count,
[&]() {
threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) {
for (const int i : range) {

View File

@ -307,6 +307,7 @@ static Mesh *create_uv_sphere_mesh(const float radius, const int segments, const
MutableSpan<MPoly> polys{mesh->mpoly, mesh->totpoly};
threading::parallel_invoke(
1024 < segments * rings,
[&]() {
MutableSpan vert_normals{(float3 *)BKE_mesh_vertex_normals_for_write(mesh), mesh->totvert};
calculate_sphere_vertex_data(verts, vert_normals, radius, segments, rings);