diff --git a/SeQuant/core/eval/backends/tiledarray/result.hpp b/SeQuant/core/eval/backends/tiledarray/result.hpp index c38640b985..2c9047e380 100644 --- a/SeQuant/core/eval/backends/tiledarray/result.hpp +++ b/SeQuant/core/eval/backends/tiledarray/result.hpp @@ -317,8 +317,14 @@ class ResultTensorOfTensorTA final : public Result { using _inner_tensor_type = typename ArrayT::value_type::value_type; + // "Regular" (non-nested) companion array for ToT * T einsum. The OUTER tile + // type must be a TA::Tensor — inner tile types like btas::Tensor are only + // valid as the *innermost* tile (they don't support permute/reshape/batch + // and so can't drive einsum's outer kernel). So we wrap the inner's numeric + // type in TA::Tensor here, rather than re-using the inner tile type as the + // outer tile. using compatible_regular_distarray_type = - TA::DistArray<_inner_tensor_type, typename ArrayT::policy_type>; + TA::DistArray, typename ArrayT::policy_type>; // Only @c that_type type is allowed for ToT * T computation using that_type = ResultTensorTA; diff --git a/SeQuant/core/eval/cache_manager.hpp b/SeQuant/core/eval/cache_manager.hpp index 6ce8f54b2e..52dbe4657c 100644 --- a/SeQuant/core/eval/cache_manager.hpp +++ b/SeQuant/core/eval/cache_manager.hpp @@ -83,8 +83,9 @@ class CacheManager { std::unordered_map cache_map_; public: - template - explicit CacheManager(Iterable1&& decaying) noexcept { + template + requires(!std::same_as, CacheManager>) + explicit CacheManager(Iterable&& decaying) noexcept { for (auto&& [k, c] : decaying) cache_map_.try_emplace(k, entry{c}); } @@ -145,6 +146,21 @@ class CacheManager { return iter == end ? -1 : static_cast(iter->second.max_life_count()); } + /// \return true iff the key is registered for caching and currently holds + /// stored data (i.e. has been stored and not yet drained by its + /// final access). + [[nodiscard]] bool alive(key_type const& key) const noexcept { + auto iter = cache_map_.find(key); + return iter != cache_map_.end() && iter->second.alive(); + } + + /// \return size in bytes of the data currently held for @p key, or 0 if + /// the key is not registered or no data is currently stored. + [[nodiscard]] size_t entry_size_in_bytes(key_type const& key) const noexcept { + auto iter = cache_map_.find(key); + return iter == cache_map_.end() ? 0 : iter->second.size_in_bytes(); + } + /// /// \return The number of entries with life_count greater than zero. /// diff --git a/SeQuant/core/eval/eval.hpp b/SeQuant/core/eval/eval.hpp index 9f06496aa2..bf69639bb1 100644 --- a/SeQuant/core/eval/eval.hpp +++ b/SeQuant/core/eval/eval.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -33,15 +34,15 @@ struct Bytes { size_t value; }; -template - requires((std::same_as && ...)) -[[nodiscard]] auto bytes(T const&... args) { - return Bytes{(args->size_in_bytes() + ...)}; -} - -template -[[nodiscard]] inline auto bytes(CacheManager const& cman) { - return cman.size_in_bytes(); +template +[[nodiscard]] inline auto bytes(T const& arg, Ts const&... args) { + auto one = [](auto const& a) -> size_t { + if constexpr (requires { a->size_in_bytes(); }) + return a->size_in_bytes(); + else + return a.size_in_bytes(); + }; + return Bytes{(one(arg) + ... + one(args))}; } [[nodiscard]] inline auto to_string(Bytes bs) noexcept { @@ -107,10 +108,45 @@ enum struct TermMode { Begin, End }; return (mode == TermMode::Begin) ? "Begin" : "End"; } +/// One log record per eval op. Line format: +/// +// clang-format off +/// Eval | |