@@ -65,11 +65,14 @@ Long nBytesOwned (BaseFab<T> const& fab) noexcept { return fab.nBytesOwned(); }
6565struct MFInfo {
6666 // alloc: allocate memory or not
6767 bool alloc = true ;
68+ bool alloc_single_chunk = FabArrayBase::getAllocSingleChunk();
6869 Arena* arena = nullptr ;
6970 Vector<std::string> tags;
7071
7172 MFInfo& SetAlloc (bool a) noexcept { alloc = a; return *this ; }
7273
74+ MFInfo& SetAllocSingleChunk (bool a) noexcept { alloc_single_chunk = a; return *this ; }
75+
7376 MFInfo& SetArena (Arena* ar) noexcept { arena = ar; return *this ; }
7477
7578 MFInfo& SetTag () noexcept { return *this ; }
@@ -436,6 +439,22 @@ public:
436439#endif
437440 }
438441
442+ // ! Return the data pointer to the single chunk memory if this object
443+ // ! uses a single contiguous chunk of memory, nullptr otherwise.
444+ [[nodiscard]] value_type* singleChunkPtr () noexcept {
445+ return m_single_chunk_arena ? (value_type*)m_single_chunk_arena->data () : nullptr ;
446+ }
447+
448+ // ! Return the data pointer to the single chunk memory if this object
449+ // ! uses a single contiguous chunk of memory, nullptr otherwise.
450+ [[nodiscard]] value_type const * singleChunkPtr () const noexcept {
451+ return m_single_chunk_arena ? (value_type const *)m_single_chunk_arena->data () : nullptr ;
452+ }
453+
454+ // ! Return the size of the single chunk memory if this object uses a
455+ // ! single contiguous chunk of memory, 0 otherwise.
456+ [[nodiscard]] std::size_t singleChunkSize () const noexcept { return m_single_chunk_size; }
457+
439458 bool isAllRegular () const noexcept {
440459#ifdef AMREX_USE_EB
441460 const auto *const f = dynamic_cast <EBFArrayBoxFactory const *>(m_factory.get ());
@@ -1233,6 +1252,8 @@ protected:
12331252
12341253 std::unique_ptr<FabFactory<FAB> > m_factory;
12351254 DataAllocator m_dallocator;
1255+ std::unique_ptr<detail::SingleChunkArena> m_single_chunk_arena;
1256+ Long m_single_chunk_size = 0 ;
12361257
12371258 // ! has define() been called?
12381259 bool define_function_called = false ;
@@ -1306,7 +1327,8 @@ private:
13061327 using Iterator = typename std::vector<FAB*>::iterator;
13071328
13081329 void AllocFabs (const FabFactory<FAB>& factory, Arena* ar,
1309- const Vector<std::string>& tags);
1330+ const Vector<std::string>& tags,
1331+ bool alloc_single_chunk);
13101332
13111333 void setFab_assert (int K, FAB const & fab) const ;
13121334
@@ -1696,6 +1718,7 @@ FabArray<FAB>::release (int K)
16961718{
16971719 const int li = localindex (K);
16981720 if (li >= 0 && li < static_cast <int >(m_fabs_v.size ()) && m_fabs_v[li] != nullptr ) {
1721+ AMREX_ASSERT (m_single_chunk_arena == nullptr );
16991722 Long nbytes = amrex::nBytesOwned (*m_fabs_v[li]);
17001723 if (nbytes > 0 ) {
17011724 for (auto const & t : m_tags) {
@@ -1715,6 +1738,7 @@ FabArray<FAB>::release (const MFIter& mfi)
17151738{
17161739 const int li = mfi.LocalIndex ();
17171740 if (li >= 0 && li < static_cast <int >(m_fabs_v.size ()) && m_fabs_v[li] != nullptr ) {
1741+ AMREX_ASSERT (m_single_chunk_arena == nullptr );
17181742 Long nbytes = amrex::nBytesOwned (*m_fabs_v[li]);
17191743 if (nbytes > 0 ) {
17201744 for (auto const & t : m_tags) {
@@ -1755,6 +1779,12 @@ FabArray<FAB>::clear ()
17551779 updateMemUsage (t, -nbytes, nullptr );
17561780 }
17571781 }
1782+
1783+ if (m_single_chunk_arena) {
1784+ m_single_chunk_arena.reset ();
1785+ }
1786+ m_single_chunk_size = 0 ;
1787+
17581788 m_tags.clear ();
17591789
17601790 FabArrayBase::clear ();
@@ -1880,6 +1910,8 @@ FabArray<FAB>::FabArray (FabArray<FAB>&& rhs) noexcept
18801910 : FabArrayBase (static_cast <FabArrayBase&&>(rhs))
18811911 , m_factory (std::move(rhs.m_factory))
18821912 , m_dallocator (std::move(rhs.m_dallocator))
1913+ , m_single_chunk_arena(std::move(rhs.m_single_chunk_arena))
1914+ , m_single_chunk_size(std::exchange(rhs.m_single_chunk_size,0 ))
18831915 , define_function_called(rhs.define_function_called)
18841916 , m_fabs_v (std::move(rhs.m_fabs_v))
18851917#ifdef AMREX_USE_GPU
@@ -1909,6 +1941,8 @@ FabArray<FAB>::operator= (FabArray<FAB>&& rhs) noexcept
19091941 FabArrayBase::operator =(static_cast <FabArrayBase&&>(rhs));
19101942 m_factory = std::move (rhs.m_factory );
19111943 m_dallocator = std::move (rhs.m_dallocator );
1944+ m_single_chunk_arena = std::move (rhs.m_single_chunk_arena );
1945+ std::swap (m_single_chunk_size, rhs.m_single_chunk_size );
19121946 define_function_called = rhs.define_function_called ;
19131947 std::swap (m_fabs_v, rhs.m_fabs_v );
19141948#ifdef AMREX_USE_GPU
@@ -2008,7 +2042,7 @@ FabArray<FAB>::define (const BoxArray& bxs,
20082042 addThisBD ();
20092043
20102044 if (info.alloc ) {
2011- AllocFabs (*m_factory, m_dallocator.m_arena , info.tags );
2045+ AllocFabs (*m_factory, m_dallocator.m_arena , info.tags , info. alloc_single_chunk );
20122046#ifdef BL_USE_TEAM
20132047 ParallelDescriptor::MyTeam ().MemoryBarrier ();
20142048#endif
@@ -2018,8 +2052,11 @@ FabArray<FAB>::define (const BoxArray& bxs,
20182052template <class FAB >
20192053void
20202054FabArray<FAB>::AllocFabs (const FabFactory<FAB>& factory, Arena* ar,
2021- const Vector<std::string>& tags)
2055+ const Vector<std::string>& tags, bool alloc_single_chunk )
20222056{
2057+ if (shmem.alloc ) { alloc_single_chunk = false ; }
2058+ if constexpr (!IsBaseFab_v<FAB>) { alloc_single_chunk = false ; }
2059+
20232060 const int n = indexArray.size ();
20242061 const int nworkers = ParallelDescriptor::TeamSize ();
20252062 shmem.alloc = (nworkers > 1 );
@@ -2029,6 +2066,18 @@ FabArray<FAB>::AllocFabs (const FabFactory<FAB>& factory, Arena* ar,
20292066 FabInfo fab_info;
20302067 fab_info.SetAlloc (alloc).SetShared (shmem.alloc ).SetArena (ar);
20312068
2069+ if (alloc_single_chunk) {
2070+ m_single_chunk_size = 0L ;
2071+ for (int i = 0 ; i < n; ++i) {
2072+ int K = indexArray[i];
2073+ const Box& tmpbox = fabbox (K);
2074+ m_single_chunk_size += factory.nBytes (tmpbox, n_comp, K);
2075+ }
2076+ AMREX_ASSERT (m_single_chunk_size >= 0 ); // 0 is okay.
2077+ m_single_chunk_arena = std::make_unique<detail::SingleChunkArena>(ar, m_single_chunk_size);
2078+ fab_info.SetArena (m_single_chunk_arena.get ());
2079+ }
2080+
20322081 m_fabs_v.reserve (n);
20332082
20342083 Long nbytes = 0L ;
@@ -2136,6 +2185,7 @@ FabArray<FAB>::setFab_assert (int K, FAB const& fab) const
21362185 AMREX_ASSERT (!boxarray.empty ());
21372186 AMREX_ASSERT (fab.box () == fabbox (K));
21382187 AMREX_ASSERT (distributionMap[K] == ParallelDescriptor::MyProc ());
2188+ AMREX_ASSERT (m_single_chunk_arena == nullptr );
21392189}
21402190
21412191template <class FAB >
0 commit comments