From e3bbcd4452883cda185b0da6e7392b2dcf286c29 Mon Sep 17 00:00:00 2001 From: Jonathan Lifflander Date: Mon, 15 Jun 2020 19:24:11 -0700 Subject: [PATCH] #672: docs: write doxygen for barriers --- src/vt/collective/barrier/barrier.h | 118 ++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/src/vt/collective/barrier/barrier.h b/src/vt/collective/barrier/barrier.h index 42e67006f2..d7bcfcb698 100644 --- a/src/vt/collective/barrier/barrier.h +++ b/src/vt/collective/barrier/barrier.h @@ -59,60 +59,178 @@ namespace vt { namespace collective { namespace barrier { constexpr BarrierType const fst_barrier = 1; constexpr BarrierType const fst_coll_barrier = 0x8000000000000001; +/** + * \struct Barrier + * + * \brief Perform a collective barrier that is safe to use with VT handlers in + * flight. + * + * Align execution across multiple nodes to ensure each node across the + * communicator/runtime reach a "matching" barrier. + * + * \warning Barriers are not recommended for users for parallel + * coordination. First, barriers do not guarantee that work is actually done + * when the barrier is reached. It only ensures that the node reaches that + * point. Thus, messages sent or work enqueued for the scheduler might not be + * done when a barrier is reached. For ensuring that work is complete, use the + * create an epoch for the \c TerminationDetector component. Second, barriers + * may limit the concurrency in a program; in many causes only a reduction is + * necessary for correctness. + */ struct Barrier : virtual collective::tree::Tree { using BarrierStateType = BarrierState; + /** + * \internal \brief Construct a new barrier manager + */ Barrier(); template using ContainerType = std::unordered_map; + /** + * \internal \brief Insert/find a barrier + * + * \param[in] is_named whether the barrier is named + * \param[in] is_wait whether the barrier is of waiting type + * \param[in] barrier the barrier ID + * \param[in] cont_action (optional) continuation to attach after completion + * + * \return the barrier state + */ BarrierStateType& insertFindBarrier( bool const& is_named, bool const& is_wait, BarrierType const& barrier, ActionType cont_action = nullptr ); + /** + * \internal \brief Remove the state of a barrier + * + * \param[in] is_named whether the barrier is named + * \param[in] is_wait whether the barrier is of waiting type + * \param[in] barrier the barrier ID + */ void removeBarrier( bool const& is_named, bool const& is_wait, BarrierType const& barrier ); + /** + * \brief Rooted call to create a new named barrier, returning the ID. + * + * After calling this, one must broadcast/send this to other nodes. Typical + * use case is to put it in a message for later coordination. + * + * \return the barrier ID + */ BarrierType newNamedBarrier(); + + /** + * \brief Collective call to create a new named barrier, returning the ID. + * + * All nodes must call this in the same order to generate a consistent barrier + * ID for waiting on later. + * + * \return the barrier ID + */ BarrierType newNamedCollectiveBarrier(); + /** + * \internal \brief Send a barrier up the tree + * + * \param[in] is_named whether the barrier is named + * \param[in] is_wait whether the barrier is of waiting type + * \param[in] barrier the barrier ID + * \param[in] skip_term whether to skip termination (mark barrier a TD message) + */ void barrierUp( bool const& is_named, bool const& is_wait, BarrierType const& barrier, bool const& skip_term ); + /** + * \internal \brief Send a barrier down the tree to release nodes (barrier is + * reached!) + * + * \param[in] is_named whether the barrier is named + * \param[in] is_wait whether the barrier is of waiting type + * \param[in] barrier the barrier ID + */ void barrierDown( bool const& is_named, bool const& is_wait, BarrierType const& barrier ); + /** + * \brief Wait on a barrier + * + * \param[in] poll_action action to execute while polling for barrier + * completion in addition to polling scheduler + * \param[in] barrier the barrier ID to wait on + */ inline void barrier( ActionType poll_action = nullptr, BarrierType const& barrier = no_barrier ) { return waitBarrier(poll_action, barrier); } + /** + * \brief Collectively create a new barrier and once completed execute an + * action. + * + * \param[in] fn the action to execute after the barrier is reached by all + * nodes + */ inline void barrierThen(ActionType fn) { return contBarrier(fn); } + /** + * \brief Collective wait for a barrier and once completed execute an action. + * + * \param[in] barrier the barrier to wait on + * \param[in] fn the action to execute after the barrier is reached by all + * nodes + */ inline void barrierThen(BarrierType const& barrier, ActionType fn) { return contBarrier(fn, barrier); } + /** + * \internal \brief Collectively barrier skipping termination + * + * \warning This is dangerous to call in any code outside of internal + * initialize and finalize. + */ inline void systemMetaBarrier() { bool const skip_term = true; return waitBarrier(nullptr, no_barrier, skip_term); } + /** + * \internal \brief Collectively barrier skipping termination and then execute + * a continuation. + * + * \param[in] fn action to execute after barrier is reached + * + * \warning This is dangerous to call in any code outside of internal + * initialize and finalize. + */ inline void systemMetaBarrierCont(ActionType fn) { bool const skip_term = true; return contBarrier(fn, no_barrier, skip_term); } + /** + * \internal \brief Active handler to send a barrier up the spanning tree + * + * \param[in] msg the barrier message + */ static void barrierUp(BarrierMsg* msg); + + /** + * \internal \brief Active handler to send a barrier down the spanning tree + * + * \param[in] msg the barrier message + */ static void barrierDown(BarrierMsg* msg); private: