Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-11-26 13:05:47 +0300
committerJacques Lucke <jacques@blender.org>2021-11-26 13:06:16 +0300
commit658fd8df0bd2427cd77e7fc4bcca8a102f67b626 (patch)
tree574c5a6f4c11db7047a98ca38c6d6f129a4b10e2 /source/blender/functions/FN_multi_function_params.hh
parent004172de38d5483b715a5b13d06c2aa5dd3de3f5 (diff)
Geometry Nodes: refactor multi-threading in field evaluation
Previously, there was a fixed grain size for all multi-functions. That was not sufficient because some functions could benefit a lot from smaller grain sizes. This refactors adds a new `MultiFunction::call_auto` method which has the same effect as just calling `MultiFunction::call` but additionally figures out how to execute the specific multi-function efficiently. It determines a good grain size and decides whether the mask indices should be shifted or not. Most multi-function evaluations benefit from this, but medium sized work loads (1000 - 50000 elements) benefit from it the most. Especially when expensive multi-functions (e.g. noise) is involved. This is because for smaller work loads, threading is rarely used and for larger work loads threading worked fine before already. With this patch, multi-functions can specify execution hints, that allow the caller to execute it most efficiently. These execution hints still have to be added to more functions. Some performance measurements of a field evaluation involving noise and math nodes, ordered by the number of elements being evaluated: ``` 1,000,000: 133 ms -> 120 ms 100,000: 30 ms -> 18 ms 10,000: 20 ms -> 2.7 ms 1,000: 4 ms -> 0.5 ms 100: 0.5 ms -> 0.4 ms ```
Diffstat (limited to 'source/blender/functions/FN_multi_function_params.hh')
-rw-r--r--source/blender/functions/FN_multi_function_params.hh29
1 files changed, 14 insertions, 15 deletions
diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh
index 5c7e75230f3..f4ddc4f2881 100644
--- a/source/blender/functions/FN_multi_function_params.hh
+++ b/source/blender/functions/FN_multi_function_params.hh
@@ -25,6 +25,8 @@
* the function. `MFParams` is then used inside the called function to access the parameters.
*/
+#include <mutex>
+
#include "BLI_resource_scope.hh"
#include "FN_generic_pointer.hh"
@@ -45,6 +47,9 @@ class MFParamsBuilder {
Vector<const GVVectorArray *> virtual_vector_arrays_;
Vector<GVectorArray *> vector_arrays_;
+ std::mutex mutex_;
+ Vector<std::pair<int, GMutableSpan>> dummy_output_spans_;
+
friend class MFParams;
MFParamsBuilder(const MFSignature &signature, const IndexMask mask)
@@ -62,8 +67,8 @@ class MFParamsBuilder {
template<typename T> void add_readonly_single_input_value(T value, StringRef expected_name = "")
{
- T *value_ptr = &scope_.add_value<T>(std::move(value));
- this->add_readonly_single_input(value_ptr, expected_name);
+ this->add_readonly_single_input(VArray<T>::ForSingle(std::move(value), min_array_size_),
+ expected_name);
}
template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "")
{
@@ -254,20 +259,12 @@ class MFParams {
this->assert_correct_param(param_index, name, MFParamType::SingleOutput);
int data_index = builder_->signature_->data_index(param_index);
GMutableSpan span = builder_->mutable_spans_[data_index];
- if (span.is_empty()) {
- /* The output is ignored by the caller, but the multi-function does not handle this case. So
- * create a temporary buffer that the multi-function can write to. */
- const CPPType &type = span.type();
- void *buffer = builder_->scope_.linear_allocator().allocate(
- builder_->min_array_size_ * type.size(), type.alignment());
- if (!type.is_trivially_destructible()) {
- /* Make sure the temporary elements will be destructed in the end. */
- builder_->scope_.add_destruct_call(
- [&type, buffer, mask = builder_->mask_]() { type.destruct_indices(buffer, mask); });
- }
- span = GMutableSpan{type, buffer, builder_->min_array_size_};
+ if (!span.is_empty()) {
+ return span;
}
- return span;
+ /* The output is ignored by the caller, but the multi-function does not handle this case. So
+ * create a temporary buffer that the multi-function can write to. */
+ return this->ensure_dummy_single_output(data_index);
}
/**
@@ -356,6 +353,8 @@ class MFParams {
}
#endif
}
+
+ GMutableSpan ensure_dummy_single_output(int data_index);
};
} // namespace blender::fn