From e37aeefe023a7df9a0e6ad3629b8ded86f17c53c Mon Sep 17 00:00:00 2001 From: AlexanderSinn Date: Sun, 10 Aug 2025 15:22:13 +0200 Subject: [PATCH 1/5] Improve support for Particles with PolymorphicArenaAllocator --- Src/Base/AMReX_GpuAllocators.H | 7 +- Src/Particle/AMReX_NeighborParticlesI.H | 3 +- Src/Particle/AMReX_ParticleContainer.H | 16 +- Src/Particle/AMReX_ParticleContainerBase.H | 9 + Src/Particle/AMReX_ParticleContainerI.H | 28 ++- Src/Particle/AMReX_ParticleIO.H | 5 +- Src/Particle/AMReX_ParticleTile.H | 43 ++++- Src/Particle/AMReX_WriteBinaryParticleData.H | 185 +++++++++++++------ 8 files changed, 226 insertions(+), 70 deletions(-) diff --git a/Src/Base/AMReX_GpuAllocators.H b/Src/Base/AMReX_GpuAllocators.H index de2fc0ad6bc..5accd7ee84a 100644 --- a/Src/Base/AMReX_GpuAllocators.H +++ b/Src/Base/AMReX_GpuAllocators.H @@ -171,6 +171,9 @@ namespace amrex { template struct IsPolymorphicArenaAllocator : std::false_type {}; + template + struct IsPolymorphicArenaAllocator > : std::true_type {}; + #ifdef AMREX_USE_GPU template struct RunOnGpu > : std::true_type {}; @@ -183,10 +186,6 @@ namespace amrex { template struct RunOnGpu > : std::true_type {}; - - template - struct IsPolymorphicArenaAllocator > : std::true_type {}; - #endif // AMREX_USE_GPU #ifdef AMREX_USE_GPU diff --git a/Src/Particle/AMReX_NeighborParticlesI.H b/Src/Particle/AMReX_NeighborParticlesI.H index de5146fbe9c..1065ae09970 100644 --- a/Src/Particle/AMReX_NeighborParticlesI.H +++ b/Src/Particle/AMReX_NeighborParticlesI.H @@ -454,7 +454,8 @@ NeighborParticleContainer const Vector& map = local_map[lev][dst_index]; const int num_ghosts = map.size(); neighbors[lev][dst_index].define(this->NumRuntimeRealComps(), - this->NumRuntimeIntComps()); + this->NumRuntimeIntComps(), + nullptr, nullptr, arena()); neighbors[lev][dst_index].resize(num_ghosts); local_neighbor_sizes[lev][dst_index] = neighbors[lev][dst_index].size(); } diff --git a/Src/Particle/AMReX_ParticleContainer.H b/Src/Particle/AMReX_ParticleContainer.H index 3baafe1d34e..ca709aa5576 100644 --- a/Src/Particle/AMReX_ParticleContainer.H +++ b/Src/Particle/AMReX_ParticleContainer.H @@ -197,6 +197,9 @@ public: using ParIterType = ParIter_impl; using ParConstIterType = ParConstIter_impl; + static constexpr bool has_polymorphic_allocator = + IsPolymorphicArenaAllocator>::value; + //! \brief Default constructor - construct an empty particle container that has no concept //! of a level hierarchy. Must be properly initialized later. ParticleContainer_impl () @@ -1156,8 +1159,11 @@ public: */ ParticleTileType& DefineAndReturnParticleTile (int lev, int grid, int tile) { - m_particles[lev][std::make_pair(grid, tile)].define(NumRuntimeRealComps(), NumRuntimeIntComps(), &m_soa_rdata_names, &m_soa_idata_names); - + m_particles[lev][std::make_pair(grid, tile)].define( + NumRuntimeRealComps(), NumRuntimeIntComps(), + &m_soa_rdata_names, &m_soa_idata_names, + arena() + ); return ParticlesAt(lev, grid, tile); } @@ -1186,7 +1192,11 @@ public: ParticleTileType& DefineAndReturnParticleTile (int lev, const Iterator& iter) { auto index = std::make_pair(iter.index(), iter.LocalTileIndex()); - m_particles[lev][index].define(NumRuntimeRealComps(), NumRuntimeIntComps(), &m_soa_rdata_names, &m_soa_idata_names); + m_particles[lev][index].define( + NumRuntimeRealComps(), NumRuntimeIntComps(), + &m_soa_rdata_names, &m_soa_idata_names, + arena() + ); return ParticlesAt(lev, iter); } diff --git a/Src/Particle/AMReX_ParticleContainerBase.H b/Src/Particle/AMReX_ParticleContainerBase.H index 0f573b9d163..7cb4fe62839 100644 --- a/Src/Particle/AMReX_ParticleContainerBase.H +++ b/Src/Particle/AMReX_ParticleContainerBase.H @@ -245,6 +245,14 @@ public: template bool OnSameGrids (int level, const MF& mf) const { return m_gdb->OnSameGrids(level, mf); } + [[nodiscard]] Arena* arena () const { + return m_arena; + } + + void SetArena (Arena* a) { + m_arena = a; + } + static const std::string& CheckpointVersion (); static const std::string& PlotfileVersion (); static const std::string& DataPrefix (); @@ -269,6 +277,7 @@ protected: std::unique_ptr m_gdb_object = std::make_unique(); ParGDBBase* m_gdb{nullptr}; Vector > m_dummy_mf; + Arena* m_arena = nullptr; mutable std::unique_ptr redistribute_mask_ptr; mutable int redistribute_mask_nghost = std::numeric_limits::min(); diff --git a/Src/Particle/AMReX_ParticleContainerI.H b/Src/Particle/AMReX_ParticleContainerI.H index 1d90fde2c76..eab4509685a 100644 --- a/Src/Particle/AMReX_ParticleContainerI.H +++ b/Src/Particle/AMReX_ParticleContainerI.H @@ -1255,8 +1255,11 @@ ParticleContainer_impl pinned_ptile; - pinned_ptile.define(NumRuntimeRealComps(), NumRuntimeIntComps()); + amrex::PolymorphicArenaAllocator> pinned_ptile; + pinned_ptile.define(NumRuntimeRealComps(), NumRuntimeIntComps(), + nullptr, nullptr, The_Pinned_Arena()); pinned_ptile.resize(kv.second.numParticles()); amrex::copyParticles(pinned_ptile, kv.second); const auto& host_aos = pinned_ptile.GetArrayOfStructs(); diff --git a/Src/Particle/AMReX_ParticleTile.H b/Src/Particle/AMReX_ParticleTile.H index d4407942521..2bcc1b569fd 100644 --- a/Src/Particle/AMReX_ParticleTile.H +++ b/Src/Particle/AMReX_ParticleTile.H @@ -748,6 +748,9 @@ struct ParticleTile using ParticleTileDataType = ParticleTileData; using ConstParticleTileDataType = ConstParticleTileData; + static constexpr bool has_polymorphic_allocator = + IsPolymorphicArenaAllocator>::value; + ParticleTile () = default; #ifndef _WIN32 // workaround windows compiler bug @@ -764,15 +767,51 @@ struct ParticleTile int a_num_runtime_real, int a_num_runtime_int, std::vector* soa_rdata_names=nullptr, - std::vector* soa_idata_names=nullptr + std::vector* soa_idata_names=nullptr, + Arena* a_arena=nullptr ) { - m_defined = true; GetStructOfArrays().define(a_num_runtime_real, a_num_runtime_int, soa_rdata_names, soa_idata_names); m_runtime_r_ptrs.resize(a_num_runtime_real); m_runtime_i_ptrs.resize(a_num_runtime_int); m_runtime_r_cptrs.resize(a_num_runtime_real); m_runtime_i_cptrs.resize(a_num_runtime_int); + + if constexpr (has_polymorphic_allocator) { + if (m_defined) { + // it is not allowed to change the arena after the tile has been defined + if constexpr (ParticleType::is_soa_particle) { + AMREX_ALWAYS_ASSERT_WITH_MESSAGE( + a_arena == GetStructOfArrays().GetIdCPUData().arena(), + "ParticleTile with PolymorphicArenaAllocator redefined with " + "different memory arena"); + } else { + AMREX_ALWAYS_ASSERT_WITH_MESSAGE( + a_arena == m_aos_tile().arena(), + "ParticleTile with PolymorphicArenaAllocator redefined with " + "different memory arena"); + } + } + + AMREX_ALWAYS_ASSERT_WITH_MESSAGE(a_arena != nullptr, + "ParticleTile with PolymorphicArenaAllocator defined with no memory arena! " + "Make sure to call setArena() on the ParticleContainer before initialization or " + "to pass an Arena to ParticleTile::define()"); + + if constexpr (ParticleType::is_soa_particle) { + GetStructOfArrays().GetIdCPUData().setArena(a_arena); + } else { + m_aos_tile().setArena(a_arena); + } + for (int j = 0; j < NumRealComps(); ++j) { + GetStructOfArrays().GetRealData(j).setArena(a_arena); + } + for (int j = 0; j < NumIntComps(); ++j) { + GetStructOfArrays().GetIntData(j).setArena(a_arena); + } + } + + m_defined = true; } // Get id data diff --git a/Src/Particle/AMReX_WriteBinaryParticleData.H b/Src/Particle/AMReX_WriteBinaryParticleData.H index 4a5117a1d29..bac3be3ec4d 100644 --- a/Src/Particle/AMReX_WriteBinaryParticleData.H +++ b/Src/Particle/AMReX_WriteBinaryParticleData.H @@ -29,12 +29,11 @@ std::size_t PSizeInFile (const Vector& wrc, const Vector& wic) return rsize + isize + AMREX_SPACEDIM*sizeof(ParticleReal) + 2*sizeof(int); } -template