|
35 | 35 | #include "TiledArray/util/random.h" |
36 | 36 |
|
37 | 37 | #include <madness/world/parallel_archive.h> |
| 38 | +#include <array> |
38 | 39 | #include <cstdlib> |
39 | 40 | #include <tuple> |
| 41 | +#include <vector> |
40 | 42 |
|
41 | 43 | namespace TiledArray { |
42 | 44 |
|
@@ -2015,6 +2017,95 @@ std::size_t size_of(const DistArray<Tile, Policy>& da) { |
2015 | 2017 | return result; |
2016 | 2018 | } |
2017 | 2019 |
|
| 2020 | +/// \return the number of bytes the locally-owned tiles of \p storage occupy |
| 2021 | +/// in memory space `S`. |
| 2022 | +/// |
| 2023 | +/// This is the *tile-data* footprint of a `DistArray`'s storage object only. |
| 2024 | +/// It deliberately does **not** include the `DistArray`-level metadata -- |
| 2025 | +/// `TiledRange`, `Shape`, and `Pmap` -- because those live in the owning |
| 2026 | +/// `ArrayImpl`/`TensorImpl`, not in the `DistributedStorage`. For |
| 2027 | +/// `SparsePolicy` the `Shape` (a per-tile Frobenius-norm table) can be |
| 2028 | +/// sizeable, so this undercounts the full per-array footprint that |
| 2029 | +/// `size_of(const DistArray&)` reports. Counts only tiles whose futures are |
| 2030 | +/// set; pending and remote-cached tiles are skipped. |
| 2031 | +/// \tparam S the memory space to report |
| 2032 | +template <MemorySpace S, typename T> |
| 2033 | +std::size_t size_of(const detail::DistributedStorage<T>& storage) { |
| 2034 | + std::size_t result = 0; |
| 2035 | + storage.for_each_local_tile( |
| 2036 | + [&result](const auto& tile) { result += size_of<S>(tile); }); |
| 2037 | + return result; |
| 2038 | +} |
| 2039 | + |
| 2040 | +/// \return the per-rank tile-data bytes (in memory space `S`) of the |
| 2041 | +/// `DistributedStorage` of *all* live `DistArray<Tile,Policy>` of the |
| 2042 | +/// requested type currently registered in \p world, discovered by walking |
| 2043 | +/// the World's `WorldObject` registry. |
| 2044 | +/// |
| 2045 | +/// Each array's tile storage is a single `detail::DistributedStorage` |
| 2046 | +/// `WorldObject`, so an array referenced by N shallow-copy handles is counted |
| 2047 | +/// exactly once — unlike summing `size_of` over a set of handles, which |
| 2048 | +/// double-counts shared storage. This makes the result suitable as ground |
| 2049 | +/// truth for validating handle-based tile-data accounting. |
| 2050 | +/// |
| 2051 | +/// Discovery is type-safe: each registered pointer is recovered as the common |
| 2052 | +/// polymorphic base `madness::WorldObjectBase` and `dynamic_cast` to the |
| 2053 | +/// `DistributedStorage` matching `DistArrayT`'s tile type; non-matching |
| 2054 | +/// objects (other tile types, MADNESS containers) are skipped. Assumes the |
| 2055 | +/// registered `WorldObject`s place `WorldObjectBase` at offset 0 (true for |
| 2056 | +/// the single-inheritance `class X : public WorldObject<X>` idiom TA uses). |
| 2057 | +/// |
| 2058 | +/// \warning This reports the `DistributedStorage` (tile-data) footprint only. |
| 2059 | +/// It excludes the `DistArray`-level `TiledRange`, `Shape`, and `Pmap`; the |
| 2060 | +/// `Shape` can be large under `SparsePolicy`. It is therefore **not** |
| 2061 | +/// comparable term-for-term with a sum of `size_of(const DistArray&)` over |
| 2062 | +/// handles (which includes the shape). Use it for tile-data accounting, not |
| 2063 | +/// total-DistArray-footprint accounting. |
| 2064 | +/// \note Counts only locally-owned tiles whose futures are set. Excludes |
| 2065 | +/// remote-tile caches. Call at a quiescent point (after a fence). |
| 2066 | +/// \tparam DistArrayT the `DistArray` specialization to look for |
| 2067 | +/// \tparam S the memory space to report (default `Host`) |
| 2068 | +template <typename DistArrayT, MemorySpace S = MemorySpace::Host> |
| 2069 | +std::size_t size_of_live_distarray_storage(World& world) { |
| 2070 | + using tile_type = typename DistArrayT::value_type; |
| 2071 | + using storage_type = detail::DistributedStorage<tile_type>; |
| 2072 | + std::size_t result = 0; |
| 2073 | + for (const auto& id : world.get_object_ids()) { |
| 2074 | + auto base_opt = world.template ptr_from_id<madness::WorldObjectBase>(id); |
| 2075 | + if (!base_opt || !*base_opt) continue; |
| 2076 | + if (auto* storage = dynamic_cast<storage_type*>(*base_opt)) { |
| 2077 | + result += size_of<S>(*storage); |
| 2078 | + } |
| 2079 | + } |
| 2080 | + return result; |
| 2081 | +} |
| 2082 | + |
| 2083 | +/// \return a matrix of per-rank live-storage tile-data byte totals indexed |
| 2084 | +/// `[world_index][type_index]`: for each `World` in \p worlds (rows) and each |
| 2085 | +/// `DistArray` type in the pack `DistArrayTs` (columns), the value of |
| 2086 | +/// `size_of_live_distarray_storage<DistArrayT, S>(world)`. Lets a caller |
| 2087 | +/// inventory which array types hold how much tile data in which world at a |
| 2088 | +/// checkpoint, deduplicated across shallow-copy handles. |
| 2089 | +/// |
| 2090 | +/// \warning Tile-data only; see `size_of_live_distarray_storage` for the |
| 2091 | +/// excluded-metadata caveat (no `TiledRange`/`Shape`/`Pmap`). |
| 2092 | +/// \note `S` is the leading template argument (it has a default but precedes |
| 2093 | +/// the type pack), so callers must spell it out: |
| 2094 | +/// `size_of_live_distarrays_storage<MemorySpace::Host, ArrayA, |
| 2095 | +/// ArrayB>(worlds)`. |
| 2096 | +/// \pre every pointer in \p worlds is non-null |
| 2097 | +template <MemorySpace S = MemorySpace::Host, typename... DistArrayTs> |
| 2098 | +std::vector<std::array<std::size_t, sizeof...(DistArrayTs)>> |
| 2099 | +size_of_live_distarrays_storage(const std::vector<World*>& worlds) { |
| 2100 | + std::vector<std::array<std::size_t, sizeof...(DistArrayTs)>> result; |
| 2101 | + result.reserve(worlds.size()); |
| 2102 | + for (World* w : worlds) { |
| 2103 | + TA_ASSERT(w != nullptr); |
| 2104 | + result.push_back({size_of_live_distarray_storage<DistArrayTs, S>(*w)...}); |
| 2105 | + } |
| 2106 | + return result; |
| 2107 | +} |
| 2108 | + |
2018 | 2109 | #ifndef TILEDARRAY_HEADER_ONLY |
2019 | 2110 |
|
2020 | 2111 | extern template class DistArray<Tensor<double>, DensePolicy>; |
|
0 commit comments