WIP: Functions: new local allocator for better memory reuse and performance #104630

Draft
Jacques Lucke wants to merge 44 commits from JacquesLucke/blender:local-allocator into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 25 additions and 15 deletions
Showing only changes of commit ff17314372 - Show all commits

View File

@ -152,7 +152,7 @@ inline LocalAllocatorSet &LocalAllocator::owner_set()
return owner_set_;
}
BLI_NOINLINE inline void *LocalAllocator::allocate(const int64_t size, const int64_t alignment)
inline void *LocalAllocator::allocate(const int64_t size, const int64_t alignment)
{
LocalAllocatorPool &pool = this->get_pool(size, alignment);
BLI_assert(pool.element_size >= size);
@ -161,9 +161,9 @@ BLI_NOINLINE inline void *LocalAllocator::allocate(const int64_t size, const int
return this->allocate(pool);
}
BLI_NOINLINE inline void LocalAllocator::deallocate(const void *buffer,
const int64_t size,
const int64_t alignment)
inline void LocalAllocator::deallocate(const void *buffer,
const int64_t size,
const int64_t alignment)
{
LocalAllocatorPool &pool = this->get_pool(size, alignment);
BLI_assert(pool.element_size >= size);

View File

@ -334,6 +334,7 @@ class FieldEvaluator : NonMovable, NonCopyable {
ResourceScope scope_;
const FieldContext &context_;
const IndexMask mask_;
LocalAllocator *allocator_ = nullptr;
Vector<GField> fields_to_evaluate_;
Vector<GVMutableArray> dst_varrays_;
Vector<GVArray> evaluated_varrays_;
@ -345,13 +346,18 @@ class FieldEvaluator : NonMovable, NonCopyable {
public:
/** Takes #mask by pointer because the mask has to live longer than the evaluator. */
FieldEvaluator(const FieldContext &context, const IndexMask *mask)
: context_(context), mask_(*mask)
FieldEvaluator(const FieldContext &context,
const IndexMask *mask,
LocalAllocator *allocator = nullptr)
: context_(context), mask_(*mask), allocator_(allocator)
{
}
/** Construct a field evaluator for all indices less than #size. */
FieldEvaluator(const FieldContext &context, const int64_t size) : context_(context), mask_(size)
FieldEvaluator(const FieldContext &context,
const int64_t size,
LocalAllocator *allocator = nullptr)
: context_(context), mask_(size), allocator_(allocator)
{
}
@ -474,6 +480,7 @@ class FieldEvaluator : NonMovable, NonCopyable {
* provided virtual arrays are returned.
*/
Vector<GVArray> evaluate_fields(ResourceScope &scope,
LocalAllocator *allocator,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,

View File

@ -277,6 +277,7 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
}
Vector<GVArray> evaluate_fields(ResourceScope &scope,
LocalAllocator *allocator,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,
@ -372,7 +373,7 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
MFProcedureExecutor procedure_executor{procedure};
MFParamsBuilder mf_params{procedure_executor, &mask};
MFContextBuilder mf_context;
MFContextBuilder mf_context{allocator};
/* Provide inputs to the procedure executor. */
for (const GVArray &varray : field_context_inputs) {
@ -423,7 +424,7 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
procedure, scope, field_tree_info, constant_fields_to_evaluate);
MFProcedureExecutor procedure_executor{procedure};
MFParamsBuilder mf_params{procedure_executor, 1};
MFContextBuilder mf_context;
MFContextBuilder mf_context{allocator};
/* Provide inputs to the procedure executor. */
for (const GVArray &varray : field_context_inputs) {
@ -500,7 +501,7 @@ void evaluate_constant_field(const GField &field, void *r_value)
ResourceScope scope;
FieldContext context;
Vector<GVArray> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
Vector<GVArray> varrays = evaluate_fields(scope, nullptr, {field}, IndexRange(1), context);
varrays[0].get_to_uninitialized(0, r_value);
}
@ -771,11 +772,12 @@ int FieldEvaluator::add(GField field)
static IndexMask evaluate_selection(const Field<bool> &selection_field,
const FieldContext &context,
IndexMask full_mask,
ResourceScope &scope)
ResourceScope &scope,
LocalAllocator *allocator)
{
if (selection_field) {
VArray<bool> selection =
evaluate_fields(scope, {selection_field}, full_mask, context)[0].typed<bool>();
evaluate_fields(scope, allocator, {selection_field}, full_mask, context)[0].typed<bool>();
return index_mask_from_selection(full_mask, selection, scope);
}
return full_mask;
@ -785,13 +787,14 @@ void FieldEvaluator::evaluate()
{
BLI_assert_msg(!is_evaluated_, "Cannot evaluate fields twice.");
selection_mask_ = evaluate_selection(selection_field_, context_, mask_, scope_);
selection_mask_ = evaluate_selection(selection_field_, context_, mask_, scope_, allocator_);
Array<GFieldRef> fields(fields_to_evaluate_.size());
for (const int i : fields_to_evaluate_.index_range()) {
fields[i] = fields_to_evaluate_[i];
}
evaluated_varrays_ = evaluate_fields(scope_, fields, selection_mask_, context_, dst_varrays_);
evaluated_varrays_ = evaluate_fields(
scope_, allocator_, fields, selection_mask_, context_, dst_varrays_);
BLI_assert(fields_to_evaluate_.size() == evaluated_varrays_.size());
for (const int i : fields_to_evaluate_.index_range()) {
OutputPointerInfo &info = output_pointer_infos_[i];

View File

@ -263,7 +263,7 @@ TEST(field, SameFieldTwice)
IndexMask mask{IndexRange(2)};
ResourceScope scope;
Vector<GVArray> results = evaluate_fields(
scope, {constant_field, constant_field}, mask, field_context);
scope, nullptr, {constant_field, constant_field}, mask, field_context);
VArray<int> varray1 = results[0].typed<int>();
VArray<int> varray2 = results[1].typed<int>();