SpECTRE  v2024.04.12
DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > > Class Template Reference

A distributed object (Charm++ Chare) that executes a series of Actions and is capable of sending and receiving data. Acts as an interface to Charm++. More...

#include <DistributedObject.hpp>

Public Types

using all_actions_list = tmpl::flatten< tmpl::list< typename PhaseDepActionListsPack::action_list... > >
 List of Actions in the order that generates the DataBox types.
 
using metavariables = typename ParallelComponent::metavariables
 The metavariables class passed to the Algorithm.
 
using inbox_tags_list = Parallel::get_inbox_tags< all_actions_list >
 List off all the Tags that can be received into the Inbox.
 
using array_index = typename get_array_index< typename ParallelComponent::chare_type >::template f< ParallelComponent >
 The type of the object used to uniquely identify the element of the array, group, or nodegroup. The default depends on the component, see ParallelComponentHelpers.
 
using parallel_component = ParallelComponent
 
using chare_type = typename parallel_component::chare_type
 The type of the Chare.
 
using cproxy_type = typename chare_type::template cproxy< parallel_component, array_index >
 The Charm++ proxy object type.
 
using cbase_type = typename chare_type::template cbase< parallel_component, array_index >
 The Charm++ base object type.
 
using phase_dependent_action_lists = tmpl::list< PhaseDepActionListsPack... >
 
using inbox_type = tuples::tagged_tuple_from_typelist< inbox_tags_list >
 
using all_cache_tags = get_const_global_cache_tags< metavariables >
 
using distributed_object_tags = typename Tags::distributed_object_tags< metavariables, array_index >
 
using databox_type = db::compute_databox_type< tmpl::flatten< tmpl::list< distributed_object_tags, typename parallel_component::simple_tags_from_options, Tags::GlobalCacheImplCompute< metavariables >, Tags::ResourceInfoReference< metavariables >, db::wrap_tags_in< Tags::FromGlobalCache, all_cache_tags >, Algorithm_detail::action_list_simple_tags< parallel_component >, Algorithm_detail::action_list_compute_tags< parallel_component > > > >
 

Public Member Functions

template<class... InitializationTags>
 DistributedObject (const Parallel::CProxy_GlobalCache< metavariables > &global_cache_proxy, tuples::TaggedTuple< InitializationTags... > initialization_items)
 Constructor used by Main to initialize the algorithm.
 
 DistributedObject (const Parallel::CProxy_GlobalCache< metavariables > &global_cache_proxy, Parallel::Phase current_phase, std::unordered_map< Parallel::Phase, size_t > phase_bookmarks, const std::unique_ptr< Parallel::Callback > &callback)
 Constructor used to dynamically add a new element of an array The callback is executed after the element is created.
 
 DistributedObject (CkMigrateMessage *)
 Charm++ migration constructor, used after a chare is migrated.
 
std::string print_types () const
 Print the expanded type aliases.
 
std::string print_state () const
 Print the current state of the algorithm.
 
std::string print_inbox () const
 Print the current contents of the inboxes.
 
std::string print_databox () const
 Print the current contents of the DataBox.
 
const auto & get_inboxes () const
 Get read access to all the inboxes.
 
void pup (PUP::er &p) override
 
template<typename Action , typename Arg >
void reduction_action (Arg arg)
 Calls the apply function Action after a reduction has been completed. More...
 
template<typename Action , typename... Args>
void simple_action (std::tuple< Args... > args)
 Explicitly call the action Action.
 
template<typename Action >
void simple_action ()
 
template<typename Action , typename... Args>
Action::return_type local_synchronous_action (Args &&... args)
 Call the Action sychronously, returning a result without any parallelization. The action is called immediately and control flow returns to the caller immediately upon completion. More...
 
template<typename ReceiveTag , typename ReceiveDataType >
void receive_data (typename ReceiveTag::temporal_id instance, ReceiveDataType &&t, bool enable_if_disabled=false)
 Receive data and store it in the Inbox, and try to continue executing the algorithm. More...
 
template<typename ReceiveTag , typename MessageType >
void receive_data (MessageType *message)
 
void start_phase (const Parallel::Phase next_phase)
 Start execution of the phase-dependent action list in next_phase. If next_phase has already been visited, execution will resume at the point where the previous execution of the same phase left off.
 
Phase phase () const
 Get the current phase.
 
const std::unordered_map< Parallel::Phase, size_t > & phase_bookmarks () const
 Get the phase bookmarks. More...
 
constexpr void set_terminate (const bool t)
 Tell the Algorithm it should no longer execute the algorithm. This does not mean that the execution of the program is terminated, but only that the algorithm has terminated. An algorithm can be restarted by passing true as the second argument to the receive_data method or by calling perform_algorithm(true).
 
constexpr bool get_terminate () const
 Check if an algorithm should continue being evaluated.
 
template<typename ThisAction , typename PhaseIndex , typename DataBoxIndex >
bool invoke_iterable_action ()
 
void contribute_termination_status_to_main ()
 Does a reduction over the component of the reduction status sending the result to Main's did_all_elements_terminate member function.
 
const std::stringdeadlock_analysis_next_iterable_action () const
 Returns the name of the last "next iterable action" to be run before a deadlock occurred.
 
template<typename Action , typename... Args, Requires<((void) sizeof...(Args), std::is_same_v< Parallel::Algorithms::Nodegroup, chare_type >)> = nullptr>
void threaded_action (std::tuple< Args... > args)
 Call an Action on a local nodegroup requiring the Action to handle thread safety. More...
 
template<typename Action >
void threaded_action ()
 Call an Action on a local nodegroup requiring the Action to handle thread safety. More...
 
void perform_algorithm ()
 Start evaluating the algorithm until it is stopped by an action.
 
void perform_algorithm (const bool restart_if_terminated)
 Start evaluating the algorithm until it is stopped by an action.
 
int number_of_procs () const
 Wrappers for charm++ informational functions. More...
 
int my_proc () const
 Index of my processing element.
 
int number_of_nodes () const
 Number of nodes.
 
int my_node () const
 Index of my node.
 
int procs_on_node (const int node_index) const
 Number of processing elements on the given node.
 
int my_local_rank () const
 The local index of my processing element on my node. This is in the interval 0, ..., procs_on_node(my_node()) - 1.
 
int first_proc_on_node (const int node_index) const
 Index of first processing element on the given node.
 
int node_of (const int proc_index) const
 Index of the node for the given processing element.
 
int local_rank_of (const int proc_index) const
 The local index for the given processing element on its node.
 

Detailed Description

template<typename ParallelComponent, typename... PhaseDepActionListsPack>
class DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >

A distributed object (Charm++ Chare) that executes a series of Actions and is capable of sending and receiving data. Acts as an interface to Charm++.

Different Types of Algorithms

Charm++ chares can be one of four types, which is specified by the type alias chare_type inside the ParallelComponent. The four available types of Algorithms are:

  1. A Parallel::Algorithms::Singleton where there is only one in the entire execution of the program.
  2. A Parallel::Algorithms::Array which holds zero or more elements each of which is a distributed object on some core. An array can grow and shrink in size dynamically if need be and can also be bound to another array. That is, the bound array has the same number of elements as the array it is bound to, and elements with the same ID are on the same core.
  3. A Parallel::Algorithms::Group, which is an array but there is one element per core and they are not able to be moved around between cores. These are typically useful for gathering data from array elements on their core, and then processing or reducing it.
  4. A Parallel::Algorithms::Nodegroup, which is similar to a group except that there is one element per node. For Charm++ SMP (shared memory parallelism) builds a node corresponds to the usual definition of a node on a supercomputer. However, for non-SMP builds nodes and cores are equivalent. An important difference between groups and nodegroups is that entry methods (remote calls to functions) are not threadsafe on nodegroups. It is up to the person writing the Actions that will be executed on the Nodegroup Algorithm to ensure they are threadsafe.

What is an Algorithm?

An Algorithm is a distributed object, a Charm++ chare, that repeatedly executes a series of Actions. An Action is a struct that has a static apply function with signature:

template <typename... DbTags, typename... InboxTags, typename Metavariables,
typename ArrayIndex, typename ActionList>
static auto apply(db::DataBox<tmpl::list<DbTags...>>& box,
const GlobalCache<Metavariables>& cache,
const ArrayIndex& array_index,
const TemporalId& temporal_id, const ActionList meta);
typename get_array_index< typename ParallelComponent::chare_type >::template f< ParallelComponent > array_index
The type of the object used to uniquely identify the element of the array, group, or nodegroup....
Definition: DistributedObject.hpp:169
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:261
auto apply(F &&f, const ObservationBox< ComputeTagsList, DataBoxType > &observation_box, Args &&... args)
Apply the function object f using its nested argument_tags list of tags.
Definition: ObservationBox.hpp:238

Note that any of the arguments can be const or non-const references except array_index, which must be a const&.

Explicit instantiations of entry methods

The code in src/Parallel/CharmMain.tpp registers all entry methods, and if one is not properly registered then a static_assert explains how to have it be registered. If there is a bug in the implementation and an entry method isn't being registered or hitting a static_assert then Charm++ will give an error of the following form:

* registration happened after init Entry point: simple_action(), addr:
* 0x555a3d0e2090
* ------------- Processor 0 Exiting: Called CmiAbort ------------
* Reason: Did you forget to instantiate a templated entry method in a .ci file?
* 

If you encounter this issue please file a bug report supplying everything necessary to reproduce the issue.

Member Function Documentation

◆ local_synchronous_action()

template<typename ParallelComponent , typename... PhaseDepActionListsPack>
template<typename Action , typename... Args>
Action::return_type DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >::local_synchronous_action ( Args &&...  args)

Call the Action sychronously, returning a result without any parallelization. The action is called immediately and control flow returns to the caller immediately upon completion.

Note
Action must have a type alias return_type specifying its return type. This constraint is to simplify the variant visitation logic for the DataBox.

◆ number_of_procs()

template<typename ParallelComponent , typename... PhaseDepActionListsPack>
int DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >::number_of_procs ( ) const
inline

Wrappers for charm++ informational functions.

Number of processing elements

◆ phase_bookmarks()

template<typename ParallelComponent , typename... PhaseDepActionListsPack>
const std::unordered_map< Parallel::Phase, size_t > & DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >::phase_bookmarks ( ) const
inline

Get the phase bookmarks.

Details

These are used to allow a phase to be resumed at a specific step in its iterable action list after PhaseControl is used to temporarily switch to other phases.

◆ receive_data()

template<typename ParallelComponent , typename... PhaseDepActionListsPack>
template<typename ReceiveTag , typename ReceiveDataType >
void DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >::receive_data ( typename ReceiveTag::temporal_id  instance,
ReceiveDataType &&  t,
bool  enable_if_disabled = false 
)

Receive data and store it in the Inbox, and try to continue executing the algorithm.

When an algorithm has terminated it can be restarted by passing enable_if_disabled = true. This allows long-term disabling and re-enabling of algorithms

◆ reduction_action()

template<typename ParallelComponent , typename... PhaseDepActionListsPack>
template<typename Action , typename Arg >
void DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >::reduction_action ( Arg  arg)

Calls the apply function Action after a reduction has been completed.

The apply function must take arg as its last argument.

◆ threaded_action() [1/2]

template<typename ParallelComponent , typename... PhaseDepActionListsPack>
template<typename Action >
void DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >::threaded_action ( )

Call an Action on a local nodegroup requiring the Action to handle thread safety.

The Parallel::NodeLock of the nodegroup is passed to the Action instead of the action_list as a const gsl::not_null<Parallel::NodeLock*>&. The node lock can be locked with the Parallel::NodeLock::lock() function, and unlocked with Parallel::unlock(). Parallel::NodeLock::try_lock() is also provided in case something useful can be done if the lock couldn't be acquired.

◆ threaded_action() [2/2]

template<typename ParallelComponent , typename... PhaseDepActionListsPack>
template<typename Action , typename... Args, Requires<((void) sizeof...(Args), std::is_same_v< Parallel::Algorithms::Nodegroup, chare_type >)> = nullptr>
void DistributedObject< ParallelComponent, tmpl::list< PhaseDepActionListsPack... > >::threaded_action ( std::tuple< Args... >  args)
inline

Call an Action on a local nodegroup requiring the Action to handle thread safety.

The Parallel::NodeLock of the nodegroup is passed to the Action instead of the action_list as a const gsl::not_null<Parallel::NodeLock*>&. The node lock can be locked with the Parallel::NodeLock::lock() function, and unlocked with Parallel::unlock(). Parallel::NodeLock::try_lock() is also provided in case something useful can be done if the lock couldn't be acquired.


The documentation for this class was generated from the following file: