Gromacs  2025-dev-20241002-88a4191
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
List of all members | Classes | Public Member Functions | Friends
gmx::ObservablesReducer Class Reference

#include <gromacs/mdtypes/observablesreducer.h>

Description

Manage reduction of observables for registered subscribers.

Modules can require that the ObservablesReducer object to which they have subscribed do communication this step. After reduction is complete, notifications are made to the callbacks that modules previously supplied to the ObservablesReducerBuilder. Then the reduction buffer is zeroed. Thus the subscribers may not depend on the values in their buffer view after the notification callback returns, so they should do any necessary processing during that callback.

Modules are free to request reduction whenever they wish, and have no obligations to do anything at any time. In particular, they do not have to set values for their reduction buffer except when they are requesting reduction.

The ObservablesReducerBuilder object is responsible for preparing a vector of doubles and notifying the subscribers of the mutually disjoint views of the buffer that they should use for both input and output of the reduction. The ObservablesReducer object that it builds retains no record of the subscribers, because its responsibility is solely to orchestrate the MPI communication and callbacks.

Subscribers automatically use the correct ObservablesReducer object because the callback they received is bound to the correct one. The only way a module can participate in an ObservablesReducer is to have registered with its builder.

The owner of an ObservablesReducer must maintain the lifetime of the ObservablesReducer object until all subscribers no longer need it. After the destruction of an ObservablesReducer, if subscribers access their view of the communication buffer, the behavior is undefined.

Classes

class  Impl
 Impl class for ObservablesReducer. More...
 

Public Member Functions

 ObservablesReducer (std::unique_ptr< Impl > impl)
 Constructor only usable by ObservablesReducerBuilder.
 
 ObservablesReducer (ObservablesReducer &&other) noexcept
 Move constructor.
 
ObservablesReduceroperator= (ObservablesReducer &&other) noexcept
 Move assignment operator.
 
bool isReductionRequired () const
 Return whether any subscriber has required reduction soon.
 
ArrayRef< double > communicationBuffer (bool reductionRequiredExternally)
 Provide view of communication buffer for MPI reduction. More...
 
void reductionComplete (Step step)
 Called by the runner after MPI communication is complete. More...
 
void markAsReadyToReduce ()
 Notify the ObservablesReducer that it should make ready to receive new values to reduce. More...
 

Friends

class ObservablesReducerBuilder
 The builder needs to be able to make the Impl object.
 

Member Function Documentation

ArrayRef< double > gmx::ObservablesReducer::communicationBuffer ( bool  reductionRequiredExternally)

Provide view of communication buffer for MPI reduction.

If no subscriber used ReductionRequirement::Soon since the last call to reductionComplete(), then this method returns an empty buffer. Otherwise it returns a view over the buffer potentially filled by all subscribed modules.

For so long as the ObservablesReducer continues to interact with the legacy compute_globals() code, the implementation of ReductionRequirement::Eventually needs to know whether any modules using compute_globals() have already requested a reduction. This value is passed as a parameter to this method.

Parameters
[in]reductionRequiredExternallyWhether external code has required a reduction
void gmx::ObservablesReducer::markAsReadyToReduce ( )

Notify the ObservablesReducer that it should make ready to receive new values to reduce.

Any runner using the ObservablesReducer must call this method whenever a step completes, so that subscribed modules can use that information to check whether reduction is happening on the step that they expect.

The ObservablesReducer keeps track of whether reduction has already occurred this step, so that when modules request reduction it can notify them of that status. This permits them to check their own requirements, e.g. that ReductionRequirement::Soon will operate this step or next step.

For the same reason, it is also necessary to call this method at a suitable point after uses of an ObservablesReducer before the regular steps of a runner.

void gmx::ObservablesReducer::reductionComplete ( Step  step)

Called by the runner after MPI communication is complete.

Notifies all subscribers who required reduction since the last call to reductionComplete() and passes the step value so they can check internally that the simulation state is consistent.

After all notifications, zeroes the communication buffer. It is the responsibility of the subscribers that required reduction to react suitably to the data available during their notification. This ensures that modules cannot get arbitrary but realistic-looking values left behind from previous communication stages. It also ensures that subsequent communication stages will not be able to keep reducing values until they overflow or underflow. This zeroing is most efficient to do centrally in an object of this class.

The choice of zero for the sentinel value is not perfect. In principle, a value of zero is potentially significant to any subscriber, so could be provided to a subscriber as the result of an incorrect implementation of ObservablesReducer or inconsistent use by subscribers. However by construction (which is tested), the integration tests never produce a zero result from an reduced value provided by a subscriber. So, if the coverage there is high then there is good reason to expect that when a zero value is used by a subscribers it is the result of a reduction and thus significant, rather than an artefact of the zeroing of the communication buffer after notifications are complete.

The choice of zero ensures that the MPI reduction will produce a valid numerical result in all cases except when a module that required reduction set buffer contents that produced a problematic output after reduction.


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