diff --git a/.gitlab/build_dane.yml b/.gitlab/build_dane.yml index 18f5ba1a9d..d0c893294b 100644 --- a/.gitlab/build_dane.yml +++ b/.gitlab/build_dane.yml @@ -59,6 +59,13 @@ dane-gcc_13_3_1-werror-src: EXTRA_CMAKE_OPTIONS: "-DENABLE_WARNINGS_AS_ERRORS:BOOL=ON" extends: .src_build_on_dane +dane-gcc_13_3_1-umpire_host_default-werror-src: + variables: + COMPILER: "gcc@13.3.1" + HOST_CONFIG: "dane-toss_4_x86_64_ib-${COMPILER}.cmake" + EXTRA_CMAKE_OPTIONS: "-DENABLE_WARNINGS_AS_ERRORS:BOOL=ON -DAXOM_DEFAULT_HOST_ALLOCATOR=UMPIRE_HOST" + extends: .src_build_on_dane + dane-sanitizers-gcc_13_3_1-src: variables: COMPILER: "gcc@13.3.1" diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index b38d9f3444..a9c119204c 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -107,6 +107,10 @@ The Axom project release numbers follow [Semantic Versioning](http://semver.org/ - Quest: Status-returning reader/writer operations in `C2CReader`, `MFEMReader`, `ProEReader`, `STEPReader`, `STLReader`, `STLWriter`, and their parallel variants are now marked `[[nodiscard]]`. Callers that previously ignored returned status values must check them to avoid compiler diagnostics. +- Axom's host execution-space default allocator is now a configure-time policy. The default policy is malloc, regardless + of whether Axom is configured with Umpire enabled. Umpire builds may opt into the Umpire `HOST` resource with + `-DAXOM_DEFAULT_HOST_ALLOCATOR=UMPIRE_HOST`. Runtime per-use selection remains available through existing explicit + allocator-ID arguments. ### Fixed - MIR/Bump: `MergeCoordsetPoints` now only emits its node-merge `SLIC_INFO` when MIR `verbose` is enabled on the Conduit options passed through ELVIRA. diff --git a/src/axom/config.hpp.in b/src/axom/config.hpp.in index bec81ffb73..702670e4d6 100644 --- a/src/axom/config.hpp.in +++ b/src/axom/config.hpp.in @@ -81,6 +81,7 @@ * Compiler defines for library capabilities */ #cmakedefine AXOM_USE_UMPIRE_SHARED_MEMORY +#cmakedefine AXOM_DEFAULT_HOST_ALLOCATOR_USES_UMPIRE_HOST /* * Compiler defines for third-party executables diff --git a/src/axom/core/ArrayBase.hpp b/src/axom/core/ArrayBase.hpp index 7b59b50897..a35a130b9f 100644 --- a/src/axom/core/ArrayBase.hpp +++ b/src/axom/core/ArrayBase.hpp @@ -911,7 +911,7 @@ struct DeviceStagingBuffer #if defined(AXOM_USE_CUDA) && defined(AXOM_USE_UMPIRE) if(m_deviceStage) { - int allocator_id = axom::detail::getAllocatorID(); + int allocator_id = axom::detail::getDefaultHostAllocatorID(); m_staging_buf = axom::allocate(nelems, allocator_id); if(read_from_data) { @@ -1018,7 +1018,7 @@ struct ArrayOps if constexpr(std::is_default_constructible_v) { #if defined(AXOM_USE_GPU) && defined(AXOM_USE_UMPIRE) - if(space != MemorySpace::Host) + if(space != MemorySpace::Host && space != MemorySpace::Malloc) { if constexpr(std::is_trivially_default_constructible_v) { @@ -1062,7 +1062,7 @@ struct ArrayOps void fill(T* array, IndexType begin, IndexType nelems, const T& value) { #if defined(AXOM_USE_GPU) && defined(AXOM_USE_UMPIRE) - if(space != MemorySpace::Host) + if(space != MemorySpace::Host && space != MemorySpace::Malloc) { if constexpr(std::is_trivially_copyable_v) { diff --git a/src/axom/core/examples/core_array_perf.cpp b/src/axom/core/examples/core_array_perf.cpp index 4ed0ba1dbe..c0a74f9d31 100644 --- a/src/axom/core/examples/core_array_perf.cpp +++ b/src/axom/core/examples/core_array_perf.cpp @@ -161,12 +161,10 @@ int allocatorIdFromPolicy(axom::runtime_policy::Policy policy) { AXOM_UNUSED_VAR(policy); #if defined(AXOM_USE_UMPIRE) - int allocatorID = policy == axom::runtime_policy::Policy::seq - ? axom::detail::getAllocatorID() - : + int allocatorID = + policy == axom::runtime_policy::Policy::seq ? axom::detail::getDefaultHostAllocatorID() : #if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) - policy == axom::runtime_policy::Policy::omp - ? axom::detail::getAllocatorID() + policy == axom::runtime_policy::Policy::omp ? axom::detail::getDefaultHostAllocatorID() : #endif #if defined(AXOM_RUNTIME_POLICY_USE_CUDA) @@ -204,12 +202,20 @@ class MDMappingPerfTester { m_allocatorId = allocatorIdFromPolicy(params.runtimePolicy); #ifdef AXOM_USE_UMPIRE - umpire::ResourceManager& rm = umpire::ResourceManager::getInstance(); - umpire::Allocator allocator = rm.getAllocator(m_allocatorId); - std::cout << axom::fmt::format("Allocator id: {}, Umpire memory space {}", - m_allocatorId, - allocator.getName()) - << std::endl; + if(m_allocatorId == axom::MALLOC_ALLOCATOR_ID) + { + std::cout << axom::fmt::format("Allocator id: {}, malloc memory space", m_allocatorId) + << std::endl; + } + else + { + umpire::ResourceManager& rm = umpire::ResourceManager::getInstance(); + umpire::Allocator allocator = rm.getAllocator(m_allocatorId); + std::cout << axom::fmt::format("Allocator id: {}, Umpire memory space {}", + m_allocatorId, + allocator.getName()) + << std::endl; + } #else std::cout << axom::fmt::format("Allocator id: {}, default memory space", m_allocatorId) << std::endl; diff --git a/src/axom/core/execution/execution_space.hpp b/src/axom/core/execution/execution_space.hpp index f2cfd30fc9..03c12ac5dc 100644 --- a/src/axom/core/execution/execution_space.hpp +++ b/src/axom/core/execution/execution_space.hpp @@ -32,7 +32,7 @@ * with OpenMp, i.e., RAJA_ENABLE_OPENMP must be defined in the generated * RAJA/config.hpp. * - * The default memory allocator when using this execution space is HOST. + * The default memory allocator when using this execution space is malloc. * * When using this execution space, the data must reside on CPU/host memory. * diff --git a/src/axom/core/execution/internal/omp_exec.hpp b/src/axom/core/execution/internal/omp_exec.hpp index 3da39efb96..ad04b38b75 100644 --- a/src/axom/core/execution/internal/omp_exec.hpp +++ b/src/axom/core/execution/internal/omp_exec.hpp @@ -16,11 +16,6 @@ #error OMP_EXEC requires an OpenMP enabled RAJA #endif -// Umpire includes -#ifdef AXOM_USE_UMPIRE - #include "umpire/Umpire.hpp" -#endif - namespace axom { /*! @@ -41,10 +36,10 @@ struct execution_space using atomic_policy = RAJA::omp_atomic; using sync_policy = RAJA::omp_synchronize; -#ifdef AXOM_USE_UMPIRE +#ifdef AXOM_DEFAULT_HOST_ALLOCATOR_USES_UMPIRE_HOST static constexpr MemorySpace memory_space = MemorySpace::Host; #else - static constexpr MemorySpace memory_space = MemorySpace::Dynamic; + static constexpr MemorySpace memory_space = MemorySpace::Malloc; #endif AXOM_HOST_DEVICE static constexpr bool async() noexcept { return false; } @@ -52,14 +47,7 @@ struct execution_space AXOM_HOST_DEVICE static constexpr bool onDevice() noexcept { return false; } AXOM_HOST_DEVICE static constexpr char* name() noexcept { return (char*)"[OMP_EXEC]"; } - static int allocatorID() noexcept - { -#ifdef AXOM_USE_UMPIRE - return axom::getUmpireResourceAllocatorID(umpire::resource::Host); -#else - return axom::getDefaultAllocatorID(); -#endif - } + static int allocatorID() noexcept { return axom::detail::getDefaultHostAllocatorID(); } AXOM_HOST_DEVICE static constexpr runtime_policy::Policy runtimePolicy() noexcept { return runtime_policy::Policy::omp; diff --git a/src/axom/core/execution/internal/seq_exec.hpp b/src/axom/core/execution/internal/seq_exec.hpp index ce9bac758b..cde15fb027 100644 --- a/src/axom/core/execution/internal/seq_exec.hpp +++ b/src/axom/core/execution/internal/seq_exec.hpp @@ -14,11 +14,6 @@ #include "RAJA/RAJA.hpp" #endif -// Umpire includes -#ifdef AXOM_USE_UMPIRE - #include "umpire/Umpire.hpp" -#endif - namespace axom { /*! @@ -51,10 +46,10 @@ struct execution_space using sync_policy = void; -#ifdef AXOM_USE_UMPIRE +#ifdef AXOM_DEFAULT_HOST_ALLOCATOR_USES_UMPIRE_HOST static constexpr MemorySpace memory_space = MemorySpace::Host; #else - static constexpr MemorySpace memory_space = MemorySpace::Dynamic; + static constexpr MemorySpace memory_space = MemorySpace::Malloc; #endif AXOM_HOST_DEVICE static constexpr bool async() noexcept { return false; } @@ -62,14 +57,7 @@ struct execution_space AXOM_HOST_DEVICE static constexpr bool onDevice() noexcept { return false; } AXOM_HOST_DEVICE static constexpr char* name() noexcept { return (char*)"[SEQ_EXEC]"; } - static int allocatorID() noexcept - { -#ifdef AXOM_USE_UMPIRE - return axom::getUmpireResourceAllocatorID(umpire::resource::Host); -#else - return axom::getDefaultAllocatorID(); -#endif - } + static int allocatorID() noexcept { return axom::detail::getDefaultHostAllocatorID(); } AXOM_HOST_DEVICE static constexpr runtime_policy::Policy runtimePolicy() noexcept { return runtime_policy::Policy::seq; diff --git a/src/axom/core/memory_management.hpp b/src/axom/core/memory_management.hpp index 5f6fd8bd41..47837cfa67 100644 --- a/src/axom/core/memory_management.hpp +++ b/src/axom/core/memory_management.hpp @@ -157,15 +157,24 @@ inline void setDefaultAllocator(umpire::resource::MemoryResourceType resource_ty #endif /*! - * \brief Sets the default memory allocator to use. - * \param [in] allocId the Umpire allocator id + * \brief Sets the default memory allocator for the Umpire ResourceManager. + * \param [in] allocId the Axom allocator id * + * \note When Axom is compiled with Umpire and \a allocId is + * axom::MALLOC_ALLOCATOR_ID, this function sets Umpire's default + * allocator to its Host resource. * \note This function has no effect when Axom is not compiled with Umpire. */ inline void setDefaultAllocator(int allocId) { #ifdef AXOM_USE_UMPIRE umpire::ResourceManager& rm = umpire::ResourceManager::getInstance(); + if(allocId == MALLOC_ALLOCATOR_ID) + { + rm.setDefaultAllocator(rm.getAllocator(umpire::resource::Host)); + return; + } + umpire::Allocator allocator = rm.getAllocator(allocId); rm.setDefaultAllocator(allocator); #else @@ -188,6 +197,27 @@ inline int getDefaultAllocatorID() #endif } +namespace detail +{ +/*! + * \brief Returns the ID of the default host allocator. + * + * \note This is distinct from the current default allocator returned by + * axom::getDefaultAllocatorID(), which tracks Umpire's default allocator + * when Axom is configured with Umpire. + * + * \return ID of the default host allocator. + */ +inline int getDefaultHostAllocatorID() +{ +#if defined(AXOM_DEFAULT_HOST_ALLOCATOR_USES_UMPIRE_HOST) + return getUmpireResourceAllocatorID(umpire::resource::Host); +#else + return MALLOC_ALLOCATOR_ID; +#endif +} +} // namespace detail + /*! * \brief Get the allocator id from which data has been allocated. * \return Allocator id. If Umpire doesn't have an allocator for the @@ -241,7 +271,7 @@ int getSharedMemoryAllocatorID(std::size_t minSegmentSize = 0); * \brief Allocates a chunk of memory of type T. * * \param [in] n the number of elements to allocate. - * \param [in] allocID the Umpire allocator to use (optional) + * \param [in] allocID the Axom/Umpire allocator to use (optional) * * \tparam T the type of pointer returned. * @@ -260,7 +290,7 @@ inline T* allocate(std::size_t n, int allocID = getDefaultAllocatorID()) noexcep * * \param [in] n the number of elements to allocate. * \param [in] name allocation name (must be non-empty for shared memory allocators) - * \param [in] allocID the Umpire allocator to use (optional) + * \param [in] allocID the Axom/Umpire allocator to use (optional) * * \return pointer to the new allocation or a nullptr if allocation failed. */ @@ -360,6 +390,11 @@ inline T* allocate(std::size_t n, int allocID) noexcept { const std::size_t numbytes = n * sizeof(T); + if(allocID == MALLOC_ALLOCATOR_ID) + { + return static_cast(std::malloc(numbytes)); + } + #ifdef AXOM_USE_UMPIRE if(umpire::ResourceManager& rm = umpire::ResourceManager::getInstance(); rm.isAllocator(allocID)) { @@ -368,11 +403,6 @@ inline T* allocate(std::size_t n, int allocID) noexcept } #endif - if(allocID == MALLOC_ALLOCATOR_ID) - { - return static_cast(std::malloc(numbytes)); - } - std::cerr << "Unrecognized allocator id " << allocID << std::endl; axom::utilities::processAbort(); @@ -384,6 +414,12 @@ inline T* allocate(std::size_t n, const std::string& name, int allocID) noexcept { const std::size_t numbytes = n * sizeof(T); + if(allocID == MALLOC_ALLOCATOR_ID) + { + AXOM_UNUSED_VAR(name); + return static_cast(std::malloc(numbytes)); + } + #ifdef AXOM_USE_UMPIRE if(umpire::ResourceManager& rm = umpire::ResourceManager::getInstance(); rm.isAllocator(allocID)) { @@ -393,12 +429,6 @@ inline T* allocate(std::size_t n, const std::string& name, int allocID) noexcept } #endif - if(allocID == MALLOC_ALLOCATOR_ID) - { - AXOM_UNUSED_VAR(name); - return static_cast(std::malloc(numbytes)); - } - std::cerr << "Unrecognized allocator id " << allocID << std::endl; axom::utilities::processAbort(); @@ -547,13 +577,12 @@ inline void fill(void* dst, std::size_t n, const T& value) noexcept doHostFill = false; // Device memory: fill on host, then copy to device - const auto num_bytes = n * sizeof(T); - T* src = allocate(num_bytes, rm.getDefaultAllocator().getId()); + T* src = allocate(n, axom::detail::getDefaultHostAllocatorID()); for(std::size_t i = 0; i < n; ++i) { src[i] = value; } - rm.copy(dst, src, num_bytes); + axom::copy(dst, src, n * sizeof(T)); deallocate(src); } } diff --git a/src/axom/core/tests/core_execution_space.hpp b/src/axom/core/tests/core_execution_space.hpp index 749f953831..846e650fdf 100644 --- a/src/axom/core/tests/core_execution_space.hpp +++ b/src/axom/core/tests/core_execution_space.hpp @@ -118,6 +118,30 @@ TEST(core_execution_space, check_invalid) check_invalid(); } +//------------------------------------------------------------------------------ +TEST(core_execution_space, check_default_host_allocator) +{ + int expected_host_allocator = axom::MALLOC_ALLOCATOR_ID; + auto expected_host_memory_space = axom::MemorySpace::Malloc; +#if defined(AXOM_DEFAULT_HOST_ALLOCATOR_USES_UMPIRE_HOST) + expected_host_allocator = axom::getUmpireResourceAllocatorID(umpire::resource::Host); + expected_host_memory_space = axom::MemorySpace::Host; +#endif + + EXPECT_EQ(expected_host_memory_space, axom::execution_space::memory_space); + EXPECT_EQ(expected_host_allocator, axom::execution_space::allocatorID()); + +#if defined(AXOM_USE_UMPIRE) + EXPECT_EQ(axom::getUmpireResourceAllocatorID(umpire::resource::Host), + axom::detail::getAllocatorID()); +#endif + +#if defined(AXOM_USE_OPENMP) && defined(AXOM_USE_RAJA) + EXPECT_EQ(expected_host_allocator, axom::execution_space::allocatorID()); + EXPECT_EQ(expected_host_memory_space, axom::execution_space::memory_space); +#endif +} + //============================================================================== // The following tests require RAJA and UMPIRE //============================================================================== @@ -130,7 +154,7 @@ TEST(core_execution_space, check_seq_exec) constexpr bool IS_ASYNC = false; constexpr bool ON_DEVICE = false; - int allocator_id = axom::getUmpireResourceAllocatorID(umpire::resource::Host); + int allocator_id = axom::execution_space::allocatorID(); check_execution_mappings 2022 RAJA::seq_exec, @@ -153,7 +177,7 @@ TEST(core_execution_space, check_omp_exec) constexpr bool IS_ASYNC = false; constexpr bool ON_DEVICE = false; - int allocator_id = axom::getUmpireResourceAllocatorID(umpire::resource::Host); + int allocator_id = axom::execution_space::allocatorID(); check_execution_mappings::allocatorID(); #if defined(AXOM_USE_UMPIRE) auto& rm = umpire::ResourceManager::getInstance(); - umpire::Allocator allocator = rm.getAllocator(allocator_id); + umpire::Allocator allocator = allocator_id == axom::MALLOC_ALLOCATOR_ID + ? rm.getAllocator(umpire::resource::Host) + : rm.getAllocator(allocator_id); const std::string newName = allocator.getName() + "_POOL"; SLIC_INFO( @@ -211,7 +213,9 @@ int runMIR(const conduit::Node& hostMesh, const conduit::Node& options, conduit: try { auto& rm = umpire::ResourceManager::getInstance(); - umpire::Allocator allocator = rm.getAllocator(allocator_id); + umpire::Allocator allocator = allocator_id == axom::MALLOC_ALLOCATOR_ID + ? rm.getAllocator(umpire::resource::Host) + : rm.getAllocator(allocator_id); SLIC_INFO("Allocator Information:"); SLIC_INFO(axom::fmt::format("\tname: {}", allocator.getName())); SLIC_INFO(axom::fmt::format("\thighwatermark: {}", allocator.getHighWatermark())); diff --git a/src/axom/mir/examples/heavily_mixed/runMIR.hpp b/src/axom/mir/examples/heavily_mixed/runMIR.hpp index 0f7e85f9d1..0228a08efe 100644 --- a/src/axom/mir/examples/heavily_mixed/runMIR.hpp +++ b/src/axom/mir/examples/heavily_mixed/runMIR.hpp @@ -19,7 +19,9 @@ int installAllocator([[maybe_unused]] size_t initialPoolSizeBytes) int allocator_id = axom::execution_space::allocatorID(); #if defined(AXOM_USE_UMPIRE) auto& rm = umpire::ResourceManager::getInstance(); - umpire::Allocator allocator = rm.getAllocator(allocator_id); + umpire::Allocator allocator = allocator_id == axom::MALLOC_ALLOCATOR_ID + ? rm.getAllocator(umpire::resource::Host) + : rm.getAllocator(allocator_id); const std::string newName = allocator.getName() + "_POOL"; SLIC_INFO( @@ -141,7 +143,9 @@ int runMIR(const conduit::Node& hostMesh, const conduit::Node& options, conduit: try { auto& rm = umpire::ResourceManager::getInstance(); - umpire::Allocator allocator = rm.getAllocator(allocator_id); + umpire::Allocator allocator = allocator_id == axom::MALLOC_ALLOCATOR_ID + ? rm.getAllocator(umpire::resource::Host) + : rm.getAllocator(allocator_id); SLIC_INFO("Allocator Information:"); SLIC_INFO(axom::fmt::format("\tname: {}", allocator.getName())); SLIC_INFO(axom::fmt::format("\thighwatermark: {}", allocator.getHighWatermark())); diff --git a/src/axom/primal/tests/primal_intersect.cpp b/src/axom/primal/tests/primal_intersect.cpp index 66fd2c2bca..12c02bc44b 100644 --- a/src/axom/primal/tests/primal_intersect.cpp +++ b/src/axom/primal/tests/primal_intersect.cpp @@ -2592,9 +2592,8 @@ void check_plane_bb_intersect() // Determine new allocator (for CUDA or HIP policy, set to device) umpire::Allocator allocator = - (axom::execution_space::onDevice() - ? rm.getAllocator(umpire::resource::Device) - : rm.getAllocator(axom::execution_space::allocatorID())); + (axom::execution_space::onDevice() ? rm.getAllocator(umpire::resource::Device) + : rm.getAllocator(umpire::resource::Host)); // Set new default to device axom::setDefaultAllocator(allocator.getId()); @@ -2673,9 +2672,8 @@ void check_plane_seg_intersect() // Determine new allocator (for CUDA or HIP policy, set to device) umpire::Allocator allocator = - (axom::execution_space::onDevice() - ? rm.getAllocator(umpire::resource::Device) - : rm.getAllocator(axom::execution_space::allocatorID())); + (axom::execution_space::onDevice() ? rm.getAllocator(umpire::resource::Device) + : rm.getAllocator(umpire::resource::Host)); // Set new default to device axom::setDefaultAllocator(allocator.getId()); @@ -2762,9 +2760,8 @@ void check_segment_segment_intersect_policy() const int current_allocator = axom::getDefaultAllocatorID(); umpire::Allocator allocator = - (axom::execution_space::onDevice() - ? rm.getAllocator(umpire::resource::Device) - : rm.getAllocator(axom::execution_space::allocatorID())); + (axom::execution_space::onDevice() ? rm.getAllocator(umpire::resource::Device) + : rm.getAllocator(umpire::resource::Host)); axom::setDefaultAllocator(allocator.getId()); diff --git a/src/axom/quest/MarchingCubes.cpp b/src/axom/quest/MarchingCubes.cpp index 4a0d4f855e..3c1e82391b 100644 --- a/src/axom/quest/MarchingCubes.cpp +++ b/src/axom/quest/MarchingCubes.cpp @@ -195,14 +195,8 @@ void MarchingCubes::populateContourMesh(axom::mint::UnstructuredMesh() -#else - axom::detail::getAllocatorID() -#endif - : m_allocatorID; + const int hostAllocatorId = + hostAndInternalMemoriesAreSeparate ? axom::detail::getDefaultHostAllocatorID() : m_allocatorID; if(hostAndInternalMemoriesAreSeparate) { diff --git a/src/axom/quest/examples/quest_marching_cubes_example.cpp b/src/axom/quest/examples/quest_marching_cubes_example.cpp index 3c19f9734f..5c98329bab 100644 --- a/src/axom/quest/examples/quest_marching_cubes_example.cpp +++ b/src/axom/quest/examples/quest_marching_cubes_example.cpp @@ -1611,10 +1611,9 @@ int allocatorIdToTest(axom::runtime_policy::Policy policy) //--------------------------------------------------------------------------- // Memory resource. For testing, choose device memory if appropriate. //--------------------------------------------------------------------------- - int allocatorID = - policy == RuntimePolicy::seq ? axom::detail::getAllocatorID() : + int allocatorID = policy == RuntimePolicy::seq ? axom::detail::getDefaultHostAllocatorID() : #if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) - policy == RuntimePolicy::omp ? axom::detail::getAllocatorID() + policy == RuntimePolicy::omp ? axom::detail::getDefaultHostAllocatorID() : #endif #if defined(AXOM_RUNTIME_POLICY_USE_CUDA) diff --git a/src/axom/sidre/core/Group.cpp b/src/axom/sidre/core/Group.cpp index c9e35ac0f5..b8182c516d 100644 --- a/src/axom/sidre/core/Group.cpp +++ b/src/axom/sidre/core/Group.cpp @@ -17,6 +17,7 @@ #include "axom/core/Macros.hpp" #include "axom/core/MapCollection.hpp" #include "axom/core/Path.hpp" +#include "axom/core/memory_management.hpp" // Sidre headers #include "Buffer.hpp" @@ -1084,10 +1085,8 @@ Group* Group::createGroup(const std::string& path, bool is_list, bool accept_exi return nullptr; } - SLIC_ASSERT(group->getDefaultArrayAllocatorID() == m_default_array_alloc_id); - SLIC_ASSERT(group->getDefaultTupleAllocatorID() == m_default_tuple_alloc_id); - new_group->setDefaultArrayAllocator(m_default_array_alloc_id); - new_group->setDefaultTupleAllocator(m_default_tuple_alloc_id); + new_group->setDefaultArrayAllocator(group->getDefaultArrayAllocatorID()); + new_group->setDefaultTupleAllocator(group->getDefaultTupleAllocatorID()); return group->attachGroup(new_group); } @@ -1115,11 +1114,8 @@ Group* Group::createUnnamedGroup(bool is_list) return nullptr; } -#ifdef AXOM_USE_UMPIRE - // Why only do this with Umpire? BTNG. - new_group->setDefaultArrayAllocator(getDefaultArrayAllocator()); - new_group->setDefaultTupleAllocator(getDefaultTupleAllocator()); -#endif + new_group->setDefaultArrayAllocator(getDefaultArrayAllocatorID()); + new_group->setDefaultTupleAllocator(getDefaultTupleAllocatorID()); return attachGroup(new_group); } @@ -2290,13 +2286,8 @@ Group::Group(const std::string& name, DataStore* datastore, bool is_list) , m_is_list(is_list) , m_view_coll(nullptr) , m_group_coll(nullptr) -#ifdef AXOM_USE_UMPIRE - , m_default_array_alloc_id(axom::getDefaultAllocatorID()) - , m_default_tuple_alloc_id(axom::getDefaultAllocatorID()) -#else - , m_default_array_alloc_id(axom::MALLOC_ALLOCATOR_ID) - , m_default_tuple_alloc_id(axom::MALLOC_ALLOCATOR_ID) -#endif + , m_default_array_alloc_id(axom::detail::getDefaultHostAllocatorID()) + , m_default_tuple_alloc_id(axom::detail::getDefaultHostAllocatorID()) { if(is_list) { diff --git a/src/axom/sidre/tests/sidre_group.cpp b/src/axom/sidre/tests/sidre_group.cpp index d2dc061fe9..815f8e8ecc 100644 --- a/src/axom/sidre/tests/sidre_group.cpp +++ b/src/axom/sidre/tests/sidre_group.cpp @@ -4140,14 +4140,13 @@ TEST_P(UmpireTest, root_default_allocator) axom::setDefaultAllocator(allocID); DataStore dsPrime; - ASSERT_EQ(dsPrime.getRoot()->getDefaultAllocatorID(), allocID); + ASSERT_EQ(dsPrime.getRoot()->getDefaultAllocatorID(), axom::detail::getDefaultHostAllocatorID()); } TEST_P(UmpireTest, get_set_allocator) { int defaultAllocatorID = axom::getDefaultAllocatorID(); - ASSERT_EQ(root->getDefaultAllocator().getId(), defaultAllocatorID); - ASSERT_EQ(root->getDefaultAllocatorID(), defaultAllocatorID); + ASSERT_EQ(root->getDefaultAllocatorID(), axom::detail::getDefaultHostAllocatorID()); root->setDefaultAllocator(allocID); defaultAllocatorID = axom::getDefaultAllocatorID(); diff --git a/src/cmake/AxomConfig.cmake b/src/cmake/AxomConfig.cmake index fea39381cb..ec9e264346 100644 --- a/src/cmake/AxomConfig.cmake +++ b/src/cmake/AxomConfig.cmake @@ -63,6 +63,23 @@ foreach(option MPI3) endif() endforeach() +string(TOUPPER "${AXOM_DEFAULT_HOST_ALLOCATOR}" _axom_default_host_allocator_upper) +if(_axom_default_host_allocator_upper STREQUAL "MALLOC") + set(AXOM_DEFAULT_HOST_ALLOCATOR "MALLOC" CACHE STRING "Default host allocator: MALLOC or UMPIRE_HOST" FORCE) + unset(AXOM_DEFAULT_HOST_ALLOCATOR_USES_UMPIRE_HOST) +elseif(_axom_default_host_allocator_upper STREQUAL "UMPIRE_HOST") + if(NOT AXOM_USE_UMPIRE) + message(FATAL_ERROR + "AXOM_DEFAULT_HOST_ALLOCATOR=UMPIRE_HOST requires Axom to be configured with Umpire.") + endif() + set(AXOM_DEFAULT_HOST_ALLOCATOR "UMPIRE_HOST" CACHE STRING "Default host allocator: MALLOC or UMPIRE_HOST" FORCE) + set(AXOM_DEFAULT_HOST_ALLOCATOR_USES_UMPIRE_HOST TRUE) +else() + message(FATAL_ERROR + "Invalid value for AXOM_DEFAULT_HOST_ALLOCATOR. Must be 'MALLOC' or 'UMPIRE_HOST'; " + "was '${AXOM_DEFAULT_HOST_ALLOCATOR}'") +endif() + # Handle paths convert_to_native_escaped_file_path(${PROJECT_SOURCE_DIR} AXOM_SRC_DIR_NATIVE) convert_to_native_escaped_file_path(${PROJECT_BINARY_DIR} AXOM_BIN_DIR_NATIVE) diff --git a/src/cmake/AxomOptions.cmake b/src/cmake/AxomOptions.cmake index 3be6be1b51..0d2d30b8af 100644 --- a/src/cmake/AxomOptions.cmake +++ b/src/cmake/AxomOptions.cmake @@ -25,6 +25,8 @@ option(AXOM_ENABLE_SPARSEHASH "Enables Sparsehash." ON) option(AXOM_ENABLE_ALL_COMPONENTS "Enables all components by default" ON) option(AXOM_USE_64BIT_INDEXTYPE "Use 64-bit integers for axom::IndexType" ON) +set(AXOM_DEFAULT_HOST_ALLOCATOR "MALLOC" CACHE STRING "Default host allocator: MALLOC or UMPIRE_HOST") +set_property(CACHE AXOM_DEFAULT_HOST_ALLOCATOR PROPERTY STRINGS "MALLOC" "UMPIRE_HOST") # When enabled (default), Sidre will serialize tuple views of size 1 with state="SCALAR" # in its I/O metadata for compatibility with downstream readers (e.g. VisIt's Blueprint database plugin). diff --git a/src/cmake/axom-config.cmake.in b/src/cmake/axom-config.cmake.in index 66987f6603..4d9e0cb399 100644 --- a/src/cmake/axom-config.cmake.in +++ b/src/cmake/axom-config.cmake.in @@ -77,6 +77,7 @@ if(NOT AXOM_FOUND) # Configuration for Axom compiler defines set(AXOM_DEBUG_DEFINE "@AXOM_DEBUG_DEFINE@") set(AXOM_DEBUG_DEFINE_STRING "@AXOM_DEBUG_DEFINE_STRING@") + set(AXOM_DEFAULT_HOST_ALLOCATOR "@AXOM_DEFAULT_HOST_ALLOCATOR@") # Component-specific options set(AXOM_SIDRE_IO_USE_SCALAR_STATE_STRING "@AXOM_SIDRE_IO_USE_SCALAR_STATE_STRING@") diff --git a/src/docs/sphinx/quickstart_guide/config_build.rst b/src/docs/sphinx/quickstart_guide/config_build.rst index 87e1c27b20..6b00b982e9 100644 --- a/src/docs/sphinx/quickstart_guide/config_build.rst +++ b/src/docs/sphinx/quickstart_guide/config_build.rst @@ -409,6 +409,11 @@ Axom build options, compiler support, and parallelism | | | but this can be overridden by setting | | | | `AXOM_DEBUG_DEFINE` to `ON` or `OFF` | +------------------------------+---------+----------------------------------------+ +| AXOM_DEFAULT_HOST_ALLOCATOR | MALLOC | Controls the allocator used by default | +| | | for host execution spaces. Valid | +| | | values are `MALLOC` and `UMPIRE_HOST`. | +| | | `UMPIRE_HOST` requires Umpire. | ++------------------------------+---------+----------------------------------------+ | ENABLE_ALL_WARNINGS | ON | Enable extra compiler warnings | | | | in all build targets | +------------------------------+---------+----------------------------------------+