[Bf-blender-cvs] [b4a5df88fa0] functions: try using BufferCache instead of ArrayAllocator
Jacques Lucke
noreply at git.blender.org
Mon Jan 27 22:10:48 CET 2020
Commit: b4a5df88fa0112273021fb3ed6241574cfb05694
Author: Jacques Lucke
Date: Mon Jan 27 21:07:03 2020 +0100
Branches: functions
https://developer.blender.org/rBb4a5df88fa0112273021fb3ed6241574cfb05694
try using BufferCache instead of ArrayAllocator
===================================================================
A source/blender/blenlib/BLI_buffer_cache.h
M source/blender/blenlib/CMakeLists.txt
M source/blender/functions/intern/multi_functions/network.cc
===================================================================
diff --git a/source/blender/blenlib/BLI_buffer_cache.h b/source/blender/blenlib/BLI_buffer_cache.h
new file mode 100644
index 00000000000..2c7ef82c2dc
--- /dev/null
+++ b/source/blender/blenlib/BLI_buffer_cache.h
@@ -0,0 +1,85 @@
+#ifndef __BLI_BUFFER_ALLOCATOR_H__
+#define __BLI_BUFFER_ALLOCATOR_H__
+
+#include "BLI_vector.h"
+
+namespace BLI {
+
+class BufferCache {
+ private:
+ static const int Alignment = 64;
+
+ struct BufferHead {
+ uint buffer_size_in_bytes;
+
+ void *user_ptr()
+ {
+ BLI_STATIC_ASSERT(sizeof(BufferHead) <= Alignment, "");
+ return POINTER_OFFSET(this, Alignment);
+ }
+
+ static BufferHead *FromUserPtr(void *ptr)
+ {
+ return (BufferHead *)POINTER_OFFSET(ptr, -Alignment);
+ }
+ };
+
+ Vector<BufferHead *, 16> m_all_buffers;
+ Vector<BufferHead *, 16> m_cached_buffers;
+
+ public:
+ BufferCache() = default;
+
+ ~BufferCache()
+ {
+ BLI_assert(m_cached_buffers.size() == m_all_buffers.size());
+
+ for (BufferHead *head : m_all_buffers) {
+ MEM_freeN((void *)head);
+ }
+ }
+
+ void *allocate(uint size, uint alignment)
+ {
+ UNUSED_VARS_NDEBUG(alignment);
+ BLI_assert(alignment <= Alignment);
+
+ /* Only use buffer sizes that are a power of two, to make them easier to reuse. */
+ uint padded_size = power_of_2_max_u(size);
+
+ /* Try to use a cached memory buffer. Start searching from the back to prefer buffers that have
+ * been used "just before". */
+ for (int i = m_cached_buffers.size() - 1; i >= 0; i--) {
+ BufferHead *head = m_cached_buffers[i];
+ if (head->buffer_size_in_bytes == padded_size) {
+ void *user_ptr = head->user_ptr();
+ m_cached_buffers.remove_and_reorder(i);
+ // std::cout << "Reuse buffer\n";
+ return user_ptr;
+ }
+ }
+
+ BufferHead *new_head = (BufferHead *)MEM_mallocN_aligned(
+ padded_size + Alignment, Alignment, "allocate in BufferCache");
+ new_head->buffer_size_in_bytes = padded_size;
+ m_all_buffers.append(new_head);
+ // std::cout << "New buffer\n";
+ return new_head->user_ptr();
+ }
+
+ void deallocate(void *buffer)
+ {
+ BufferHead *head = BufferHead::FromUserPtr(buffer);
+ BLI_assert(m_all_buffers.contains(head));
+ m_cached_buffers.append(head);
+ }
+
+ void *allocate(uint element_amount, uint element_size, uint alignment)
+ {
+ return this->allocate(element_amount * element_size, alignment);
+ }
+};
+
+} // namespace BLI
+
+#endif /* __BLI_BUFFER_ALLOCATOR_H__ */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index efe7c6f8c8a..d87bfe94e85 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -279,6 +279,7 @@ set(SRC
BLI_index_to_ref_map.h
BLI_rand_cxx.h
BLI_array_allocator.h
+ BLI_buffer_cache.h
)
set(LIB
diff --git a/source/blender/functions/intern/multi_functions/network.cc b/source/blender/functions/intern/multi_functions/network.cc
index ea196217643..b5272495c13 100644
--- a/source/blender/functions/intern/multi_functions/network.cc
+++ b/source/blender/functions/intern/multi_functions/network.cc
@@ -1,10 +1,10 @@
#include "network.h"
-#include "BLI_array_allocator.h"
+#include "BLI_buffer_cache.h"
namespace FN {
-using BLI::ArrayAllocator;
+using BLI::BufferCache;
using BLI::ScopedVector;
namespace OutputValueType {
@@ -71,19 +71,18 @@ struct VectorValue : public OutputValue {
class NetworkEvaluationStorage {
private:
MonotonicAllocator<256> m_allocator;
- ArrayAllocator &m_array_allocator;
+ BufferCache &m_buffer_cache;
IndexMask m_mask;
Array<OutputValue *> m_value_per_output_id;
uint m_min_array_size;
public:
- NetworkEvaluationStorage(ArrayAllocator &array_allocator, IndexMask mask, uint socket_id_amount)
- : m_array_allocator(array_allocator),
+ NetworkEvaluationStorage(BufferCache &buffer_cache, IndexMask mask, uint socket_id_amount)
+ : m_buffer_cache(buffer_cache),
m_mask(mask),
m_value_per_output_id(socket_id_amount, nullptr),
m_min_array_size(mask.min_array_size())
{
- BLI_assert(array_allocator.array_size() >= m_min_array_size);
}
~NetworkEvaluationStorage()
@@ -100,8 +99,8 @@ class NetworkEvaluationStorage {
type.destruct(array_ref.buffer());
}
else {
- type.destruct_indices(value->array_ref.buffer(), m_mask);
- m_array_allocator.deallocate(type.size(), value->array_ref.buffer());
+ type.destruct_indices(array_ref.buffer(), m_mask);
+ m_buffer_cache.deallocate(array_ref.buffer());
}
}
else if (any_value->type == OutputValueType::Vector) {
@@ -165,8 +164,8 @@ class NetworkEvaluationStorage {
type.destruct(array_ref.buffer());
}
else {
- type.destruct_indices(value->array_ref.buffer(), m_mask);
- m_array_allocator.deallocate(type.size(), value->array_ref.buffer());
+ type.destruct_indices(array_ref.buffer(), m_mask);
+ m_buffer_cache.deallocate(array_ref.buffer());
}
m_value_per_output_id[origin.id()] = nullptr;
}
@@ -215,7 +214,7 @@ class NetworkEvaluationStorage {
BLI_assert(m_value_per_output_id[socket.id()] == nullptr);
const CPPType &type = socket.data_type().single__cpp_type();
- void *buffer = m_array_allocator.allocate(type.size(), type.alignment());
+ void *buffer = m_buffer_cache.allocate(m_min_array_size, type.size(), type.alignment());
GenericMutableArrayRef array_ref(type, buffer, m_min_array_size);
auto *value = m_allocator.construct<SingleValue>(array_ref, socket.target_amount(), false);
@@ -289,7 +288,7 @@ class NetworkEvaluationStorage {
GenericVirtualListRef list_ref = this->get_single_input__full(input);
const CPPType &type = list_ref.type();
- void *new_buffer = m_array_allocator.allocate(type.size(), type.alignment());
+ void *new_buffer = m_buffer_cache.allocate(m_min_array_size, type.size(), type.alignment());
GenericMutableArrayRef new_array_ref(type, new_buffer, m_min_array_size);
list_ref.materialize_to_uninitialized(m_mask, new_array_ref);
@@ -545,10 +544,10 @@ void MF_EvaluateNetwork::call(IndexMask mask, MFParams params, MFContext context
return;
}
- ArrayAllocator array_allocator(mask.min_array_size());
+ BufferCache buffer_cache;
const MFNetwork &network = m_outputs[0]->node().network();
- Storage storage(array_allocator, mask, network.socket_ids().size());
+ Storage storage(buffer_cache, mask, network.socket_ids().size());
this->copy_inputs_to_storage(params, storage);
this->evaluate_network_to_compute_outputs(context, storage);
this->copy_computed_values_to_outputs(params, storage);
More information about the Bf-blender-cvs
mailing list