diff --git a/CMakeLists.txt b/CMakeLists.txt index bd0ab80d..0f3d2807 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,10 @@ option(CPPUDDLE_WITH_KOKKOS "Enable KOKKOS tests/examples" OFF) option(CPPUDDLE_WITH_CLANG_TIDY "Enable clang tidy warnings" OFF) option(CPPUDDLE_WITH_CLANG_FORMAT "Enable clang format target" OFF) +# backported flags for performance experiments +option(CPPUDDLE_WITH_BUFFER_RECYCLING "Enables the default recycling behaviour! Turning this off will have a major negative performance impact and is only intended for testing!" ON) +option(CPPUDDLE_WITH_AGGRESSIVE_CONTENT_RECYCLING "Allows the aggressive allocators variants to reuse contents from previous buffers (and thus skip initializations)" ON) + if (CPPUDDLE_WITH_CUDA) enable_language(CUDA) endif () @@ -113,6 +117,21 @@ $ $ ) +# Backported flags handling +if(CPPUDDLE_WITH_BUFFER_RECYCLING) + message(INFO " Using default buffer recycling behaviour!") +else() + message(WARNING " Slow Build: Buffer recycling is deactivated. This should only be used for performance tests!") + target_compile_definitions(buffer_manager INTERFACE "CPPUDDLE_DEACTIVATE_BUFFER_RECYCLING") +endif() + +if(CPPUDDLE_WITH_AGGRESSIVE_CONTENT_RECYCLING) + message(INFO " Using default behaviour for aggressive content reusage (only relevant for aggressive allocators)!") +else() + target_compile_definitions(buffer_manager INTERFACE "CPPUDDLE_DEACTIVATE_AGGRESSIVE_ALLOCATORS") + message(WARNING " Slow Build: Aggressive allocators (and thus content recycling) is disabled. This should only be used for performance tests!") +endif() + # install libs with the defitions: install(TARGETS buffer_manager EXPORT CPPuddle LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib @@ -130,6 +149,9 @@ install(EXPORT CPPuddle NAMESPACE CPPuddle:: DESTINATION ${CMAKE_INSTALL_PREFIX} ## Add target for tests and tests definitions if (CPPUDDLE_WITH_TESTS) + if(NOT CPPUDDLE_WITH_BUFFER_RECYCLING) + message(FATAL_ERROR "The CPPuddle tests only work with CPPUDDLE_WITH_BUFFER_RECYCLING=ON. Turning off buffer recycling is not recommended in general!") + endif() add_executable(allocator_test tests/allocator_test.cpp) target_link_libraries(allocator_test ${Boost_LIBRARIES} Boost::boost Boost::program_options buffer_manager) diff --git a/include/buffer_manager.hpp b/include/buffer_manager.hpp index ff9d8ccb..8cc91f90 100644 --- a/include/buffer_manager.hpp +++ b/include/buffer_manager.hpp @@ -52,6 +52,36 @@ void destroy_n(ForwardIt first, Size n) { class buffer_recycler { // Public interface public: +#if defined(CPPUDDLE_DEACTIVATE_BUFFER_RECYCLING) + +// Warn about suboptimal performance without recycling +#pragma message \ +"Warning: Building without buffer recycling! Use only for performance testing! \ +For better performance configure CPPuddle with CPPUDDLE_WITH_BUFFER_RECYCLING=ON!" + + template + static T *get(size_t number_elements, bool manage_content_lifetime = false, + std::optional location_hint = std::nullopt, + std::optional device_id = std::nullopt) { + + return Host_Allocator{}.allocate(number_elements); + } + /// Marks an buffer as unused and fit for reusage + template + static void mark_unused(T *p, size_t number_elements, + std::optional location_hint = std::nullopt, + std::optional device_id = std::nullopt) { + return Host_Allocator{}.deallocate(p, number_elements); + } + /// Fail when internal reference counting is used but recylcing is turned off + template + static void increase_usage_counter(T *p, size_t number_elements) noexcept { + std::cerr << "ERROR: CPPuddle v0.2.1 does not support internal reference counting " + "with CPPUDDLE_WITH_BUFFER_RECYCLING=OFF. Please re-enable buffer recycling! Aborting..." + << std::endl; + abort(); + } +#else /// Returns and allocated buffer of the requested size - this may be a reused /// buffer template @@ -79,13 +109,6 @@ class buffer_recycler { return buffer_manager::mark_unused(p, number_elements); } } - - template - static void register_allocator_counters_with_hpx(void) { - std::cerr << "Warning: CPPuddle v0.2.1 does not yet support HPX counters " - "-- this operation will be ignored!" - << std::endl; - } /// Increase the reference coutner of a buffer template static void increase_usage_counter(T *p, size_t number_elements) noexcept { @@ -96,6 +119,14 @@ class buffer_recycler { p, number_elements); } } +#endif + + template + static void register_allocator_counters_with_hpx(void) { + std::cerr << "Warning: CPPuddle v0.2.1 does not yet support HPX counters " + "-- this operation will be ignored!" + << std::endl; + } /// Deallocate all buffers, no matter whether they are marked as used or not static void clean_all() { std::lock_guard guard(mut); @@ -661,6 +692,11 @@ struct aggressive_recycle_allocator { void deallocate(T *p, std::size_t n) { buffer_recycler::mark_unused(p, n); } + void increase_usage_counter(T *p, size_t n) { + buffer_recycler::increase_usage_counter(p, n); + } + +#ifndef CPPUDDLE_DEACTIVATE_AGGRESSIVE_ALLOCATORS template inline void construct(T *p, Args... args) noexcept { // Do nothing here - we reuse the content of the last owner @@ -669,9 +705,17 @@ struct aggressive_recycle_allocator { // Do nothing here - Contents will be destroyed when the buffer manager is // destroyed, not before } - void increase_usage_counter(T *p, size_t n) { - buffer_recycler::increase_usage_counter(p, n); +#else +// Warn about suboptimal performance without recycling +#pragma message \ +"Warning: Building without content reusage for aggressive allocators! \ +For better performance configure with CPPUDDLE_WITH_AGGRESSIVE_CONTENT_RECYCLING=ON !" + template + inline void construct(T *p, Args... args) noexcept { + ::new (static_cast(p)) T(std::forward(args)...); } + void destroy(T *p) { p->~T(); } +#endif }; template constexpr bool