-
Notifications
You must be signed in to change notification settings - Fork 189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an observer for tracking the size of DataBox items #5858
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Distributed under the MIT License. | ||
// See LICENSE.txt for details. | ||
|
||
#include "ParallelAlgorithms/Events/ObserveDataBox.hpp" | ||
|
||
#include <pup.h> | ||
|
||
namespace Events { | ||
ObserveDataBox::ObserveDataBox(CkMigrateMessage* /*m*/) {} | ||
|
||
void ObserveDataBox::pup(PUP::er& p) { Event::pup(p); } | ||
|
||
PUP::able::PUP_ID ObserveDataBox::my_PUP_ID = 0; // NOLINT | ||
} // namespace Events |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
// Distributed under the MIT License. | ||
// See LICENSE.txt for details. | ||
|
||
#pragma once | ||
|
||
#include <map> | ||
#include <pup.h> | ||
#include <tuple> | ||
#include <vector> | ||
|
||
#include "DataStructures/DataBox/DataBox.hpp" | ||
#include "Domain/Structure/ElementId.hpp" | ||
#include "IO/Observer/ObserverComponent.hpp" | ||
#include "IO/Observer/ReductionActions.hpp" | ||
#include "Options/String.hpp" | ||
#include "Parallel/DistributedObject.hpp" | ||
#include "Parallel/GlobalCache.hpp" | ||
#include "Parallel/Invoke.hpp" | ||
#include "Parallel/Reduction.hpp" | ||
#include "ParallelAlgorithms/EventsAndTriggers/Event.hpp" | ||
#include "Utilities/PrettyType.hpp" | ||
#include "Utilities/TMPL.hpp" | ||
|
||
namespace Events { | ||
|
||
namespace detail { | ||
|
||
struct map_add { | ||
std::map<std::string, size_t> operator()( | ||
std::map<std::string, size_t> map_1, | ||
const std::map<std::string, size_t>& map_2) { | ||
for (const auto& [key, value] : map_2) { | ||
map_1.at(key) += value; | ||
} | ||
return map_1; | ||
} | ||
}; | ||
|
||
using ReductionType = Parallel::ReductionData< | ||
// Time | ||
Parallel::ReductionDatum<double, funcl::AssertEqual<>>, | ||
// Map of total mem usage in MB per item in DataBoxes | ||
Parallel::ReductionDatum<std::map<std::string, size_t>, map_add>>; | ||
|
||
template <typename ContributingComponent> | ||
struct ReduceDataBoxSize { | ||
template <typename ParallelComponent, typename DbTags, typename Metavariables, | ||
typename ArrayIndex> | ||
static void apply(db::DataBox<DbTags>& /*box*/, | ||
Parallel::GlobalCache<Metavariables>& cache, | ||
const ArrayIndex& /*array_index*/, const double time, | ||
const std::map<std::string, size_t>& item_sizes) { | ||
auto& observer_writer_proxy = Parallel::get_parallel_component< | ||
observers::ObserverWriter<Metavariables>>(cache); | ||
const std::string subfile_name = | ||
"/DataBoxSizeInMb/" + pretty_type::name<ContributingComponent>(); | ||
std::vector<std::string> legend; | ||
legend.reserve(item_sizes.size() + 1); | ||
legend.emplace_back("Time"); | ||
std::vector<double> columns; | ||
columns.reserve(item_sizes.size() + 1); | ||
columns.emplace_back(time); | ||
const double scaling = 1.0 / 1048576.0; // so size is in MB | ||
for (const auto& [name, size] : item_sizes) { | ||
legend.emplace_back(name); | ||
columns.emplace_back(scaling * static_cast<double>(size)); | ||
} | ||
Parallel::threaded_action< | ||
observers::ThreadedActions::WriteReductionDataRow>( | ||
// Node 0 is always the writer | ||
observer_writer_proxy[0], subfile_name, legend, | ||
std::make_tuple(columns)); | ||
} | ||
}; | ||
|
||
struct ContributeDataBoxSize { | ||
template <typename ParallelComponent, typename DbTags, typename Metavariables, | ||
typename ArrayIndex> | ||
static void apply(db::DataBox<DbTags>& box, | ||
Parallel::GlobalCache<Metavariables>& cache, | ||
const ArrayIndex& array_index, const double time) { | ||
const auto& my_proxy = | ||
Parallel::get_parallel_component<ParallelComponent>(cache)[array_index]; | ||
auto& target_proxy = Parallel::get_parallel_component< | ||
observers::ObserverWriter<Metavariables>>(cache); | ||
const auto item_sizes = box.size_of_items(); | ||
if constexpr (Parallel::is_singleton_v<ParallelComponent>) { | ||
Parallel::simple_action<ReduceDataBoxSize<ParallelComponent>>( | ||
target_proxy[0], time, item_sizes); | ||
} else { | ||
Parallel::contribute_to_reduction<ReduceDataBoxSize<ParallelComponent>>( | ||
ReductionType{time, item_sizes}, my_proxy, target_proxy[0]); | ||
} | ||
} | ||
}; | ||
} // namespace detail | ||
|
||
/// \brief Event that will collect the size in MBs used by each DataBox item on | ||
/// each parallel component. | ||
/// | ||
/// \details The data will be written to disk in the reductions file under the | ||
/// `/DataBoxSizeInMb/` group. The name of each file is the `pretty_type::name` | ||
/// of each parallel component. There will be a column for each item in the | ||
/// DataBox that is not a subitem or reference item. | ||
class ObserveDataBox : public Event { | ||
public: | ||
/// \cond | ||
explicit ObserveDataBox(CkMigrateMessage* m); | ||
using PUP::able::register_constructor; | ||
WRAPPED_PUPable_decl_template(ObserveDataBox); // NOLINT | ||
/// \endcond | ||
|
||
using options = tmpl::list<>; | ||
static constexpr Options::String help = { | ||
"Observe size (in MB) of each item (except reference items) in each " | ||
"DataBox"}; | ||
|
||
ObserveDataBox() = default; | ||
|
||
using compute_tags_for_observation_box = tmpl::list<>; | ||
|
||
using return_tags = tmpl::list<>; | ||
using argument_tags = tmpl::list<::Tags::DataBox>; | ||
|
||
template <typename DataBoxType, typename ArrayIndex, | ||
typename ParallelComponent, typename Metavariables> | ||
void operator()(const DataBoxType& box, | ||
Parallel::GlobalCache<Metavariables>& /*cache*/, | ||
const ArrayIndex& array_index, | ||
const ParallelComponent* /*meta*/, | ||
const ObservationValue& observation_value) const; | ||
|
||
using is_ready_argument_tags = tmpl::list<>; | ||
|
||
template <typename Metavariables, typename ArrayIndex, typename Component> | ||
bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/, | ||
const ArrayIndex& /*array_index*/, | ||
const Component* const /*meta*/) const { | ||
return true; | ||
} | ||
|
||
bool needs_evolved_variables() const override { return false; } | ||
|
||
// NOLINTNEXTLINE(google-runtime-references) | ||
void pup(PUP::er& p) override; | ||
}; | ||
|
||
template <typename DataBoxType, typename ArrayIndex, typename ParallelComponent, | ||
typename Metavariables> | ||
void ObserveDataBox::operator()( | ||
const DataBoxType& /*box*/, Parallel::GlobalCache<Metavariables>& cache, | ||
const ArrayIndex& array_index, const ParallelComponent* const /*meta*/, | ||
const ObservationValue& observation_value) const { | ||
if (is_zeroth_element(array_index)) { | ||
using component_list = | ||
tmpl::push_back<typename Metavariables::component_list>; | ||
tmpl::for_each<component_list>([&observation_value, | ||
&cache](auto component_v) { | ||
using component = tmpl::type_from<decltype(component_v)>; | ||
auto& target_proxy = Parallel::get_parallel_component<component>(cache); | ||
Parallel::simple_action<detail::ContributeDataBoxSize>( | ||
target_proxy, observation_value.value); | ||
}); | ||
} | ||
} | ||
} // namespace Events |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some doxygen comment so this shows up?
How difficult would it be to write a simple test that just verifies this works with say 1 singleton, 1 nodegroup, and 1 array (with 3 elements?)? If it's difficult, I'm happy to defer since this feature is very necessary