Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <map>
7 : #include <pup.h>
8 : #include <tuple>
9 : #include <vector>
10 :
11 : #include "DataStructures/DataBox/DataBox.hpp"
12 : #include "Domain/Structure/ElementId.hpp"
13 : #include "IO/Observer/ObserverComponent.hpp"
14 : #include "IO/Observer/ReductionActions.hpp"
15 : #include "Options/String.hpp"
16 : #include "Parallel/DistributedObject.hpp"
17 : #include "Parallel/GlobalCache.hpp"
18 : #include "Parallel/Invoke.hpp"
19 : #include "Parallel/Reduction.hpp"
20 : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
21 : #include "Utilities/PrettyType.hpp"
22 : #include "Utilities/TMPL.hpp"
23 :
24 : namespace Events {
25 :
26 : namespace detail {
27 :
28 : struct map_add {
29 : std::map<std::string, size_t> operator()(
30 : std::map<std::string, size_t> map_1,
31 : const std::map<std::string, size_t>& map_2) {
32 : for (const auto& [key, value] : map_2) {
33 : map_1.at(key) += value;
34 : }
35 : return map_1;
36 : }
37 : };
38 :
39 : using ReductionType = Parallel::ReductionData<
40 : // Time
41 : Parallel::ReductionDatum<double, funcl::AssertEqual<>>,
42 : // Map of total mem usage in MB per item in DataBoxes
43 : Parallel::ReductionDatum<std::map<std::string, size_t>, map_add>>;
44 :
45 : template <typename ContributingComponent>
46 : struct ReduceDataBoxSize {
47 : template <typename ParallelComponent, typename DbTags, typename Metavariables,
48 : typename ArrayIndex>
49 : static void apply(db::DataBox<DbTags>& /*box*/,
50 : Parallel::GlobalCache<Metavariables>& cache,
51 : const ArrayIndex& /*array_index*/, const double time,
52 : const std::map<std::string, size_t>& item_sizes) {
53 : auto& observer_writer_proxy = Parallel::get_parallel_component<
54 : observers::ObserverWriter<Metavariables>>(cache);
55 : const std::string subfile_name =
56 : "/DataBoxSizeInMb/" + pretty_type::name<ContributingComponent>();
57 : std::vector<std::string> legend;
58 : legend.reserve(item_sizes.size() + 1);
59 : legend.emplace_back("Time");
60 : std::vector<double> columns;
61 : columns.reserve(item_sizes.size() + 1);
62 : columns.emplace_back(time);
63 : const double scaling = 1.0 / 1048576.0; // so size is in MB
64 : for (const auto& [name, size] : item_sizes) {
65 : legend.emplace_back(name);
66 : columns.emplace_back(scaling * static_cast<double>(size));
67 : }
68 : Parallel::threaded_action<
69 : observers::ThreadedActions::WriteReductionDataRow>(
70 : // Node 0 is always the writer
71 : observer_writer_proxy[0], subfile_name, legend,
72 : std::make_tuple(columns));
73 : }
74 : };
75 :
76 : struct ContributeDataBoxSize {
77 : template <typename ParallelComponent, typename DbTags, typename Metavariables,
78 : typename ArrayIndex>
79 : static void apply(db::DataBox<DbTags>& box,
80 : Parallel::GlobalCache<Metavariables>& cache,
81 : const ArrayIndex& array_index, const double time) {
82 : const auto& my_proxy =
83 : Parallel::get_parallel_component<ParallelComponent>(cache)[array_index];
84 : auto& target_proxy = Parallel::get_parallel_component<
85 : observers::ObserverWriter<Metavariables>>(cache);
86 : const auto item_sizes = box.size_of_items();
87 : if constexpr (Parallel::is_singleton_v<ParallelComponent>) {
88 : Parallel::simple_action<ReduceDataBoxSize<ParallelComponent>>(
89 : target_proxy[0], time, item_sizes);
90 : } else {
91 : Parallel::contribute_to_reduction<ReduceDataBoxSize<ParallelComponent>>(
92 : ReductionType{time, item_sizes}, my_proxy, target_proxy[0]);
93 : }
94 : }
95 : };
96 : } // namespace detail
97 :
98 : /// \brief Event that will collect the size in MBs used by each DataBox item on
99 : /// each parallel component.
100 : ///
101 : /// \details The data will be written to disk in the reductions file under the
102 : /// `/DataBoxSizeInMb/` group. The name of each file is the `pretty_type::name`
103 : /// of each parallel component. There will be a column for each item in the
104 : /// DataBox that is not a subitem or reference item.
105 1 : class ObserveDataBox : public Event {
106 : public:
107 : /// \cond
108 : explicit ObserveDataBox(CkMigrateMessage* m);
109 : using PUP::able::register_constructor;
110 : WRAPPED_PUPable_decl_template(ObserveDataBox); // NOLINT
111 : /// \endcond
112 :
113 0 : using options = tmpl::list<>;
114 0 : static constexpr Options::String help = {
115 : "Observe size (in MB) of each item (except reference items) in each "
116 : "DataBox"};
117 :
118 0 : ObserveDataBox() = default;
119 :
120 0 : using compute_tags_for_observation_box = tmpl::list<>;
121 :
122 0 : using return_tags = tmpl::list<>;
123 0 : using argument_tags = tmpl::list<::Tags::DataBox>;
124 :
125 : template <typename DataBoxType, typename ArrayIndex,
126 : typename ParallelComponent, typename Metavariables>
127 0 : void operator()(const DataBoxType& box,
128 : Parallel::GlobalCache<Metavariables>& /*cache*/,
129 : const ArrayIndex& array_index,
130 : const ParallelComponent* /*meta*/,
131 : const ObservationValue& observation_value) const;
132 :
133 0 : using is_ready_argument_tags = tmpl::list<>;
134 :
135 : template <typename Metavariables, typename ArrayIndex, typename Component>
136 0 : bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
137 : const ArrayIndex& /*array_index*/,
138 : const Component* const /*meta*/) const {
139 : return true;
140 : }
141 :
142 1 : bool needs_evolved_variables() const override { return false; }
143 :
144 : // NOLINTNEXTLINE(google-runtime-references)
145 0 : void pup(PUP::er& p) override;
146 : };
147 :
148 : template <typename DataBoxType, typename ArrayIndex, typename ParallelComponent,
149 : typename Metavariables>
150 : void ObserveDataBox::operator()(
151 : const DataBoxType& /*box*/, Parallel::GlobalCache<Metavariables>& cache,
152 : const ArrayIndex& array_index, const ParallelComponent* const /*meta*/,
153 : const ObservationValue& observation_value) const {
154 : if (is_zeroth_element(array_index)) {
155 : using component_list =
156 : tmpl::push_back<typename Metavariables::component_list>;
157 : tmpl::for_each<component_list>([&observation_value,
158 : &cache](auto component_v) {
159 : using component = tmpl::type_from<decltype(component_v)>;
160 : auto& target_proxy = Parallel::get_parallel_component<component>(cache);
161 : Parallel::simple_action<detail::ContributeDataBoxSize>(
162 : target_proxy, observation_value.value);
163 : });
164 : }
165 : }
166 : } // namespace Events
|