Abstracts the internal set of adjoint variables provided as part of the tape. More...
#include <internalAdjointsInterface.hpp>
Public Types | |
using | Gradient = T_Gradient |
See InternalAdjointsInterface. | |
using | Identifier = T_Identifier |
See InternalAdjointsInterface. | |
using | Tape = T_Tape |
See InternalAdjointsInterface. | |
Public Member Functions | |
void | beginUse () |
Declare that the adjoints are in use, e.g., during a tape evaluation, and cannot be resized right now. | |
Gradient * | data () |
Pointer to an underlying array implementation. | |
void | endUse () |
Declare that the adjoints are no longer occupied. | |
InternalAdjointsInterface (size_t initialSize) | |
Gradient & | operator[] (Identifier const &identifier) |
Reference access to the adjoint variable identified by identifier. | |
Gradient const & | operator[] (Identifier const &identifier) const |
Constant reference access to the adjoint variable identified by identifier. | |
void | resize (Identifier const &newSize) |
Ensure that identifiers up to newSize can be passed to operator[] without error. | |
size_t | size () const |
Returns the number of adjoint variables. Internally, declares usage of the adjoints. | |
template<typename Impl > | |
void | swap (Impl &other) |
Swap two sets of adjoint variables. Internally, declares usage of the adjoints. | |
void | zeroAll () |
Set all adjoint variables to Gradient(). | |
Abstracts the internal set of adjoint variables provided as part of the tape.
This interface describes the interaction between a tape and its associated adjoint variables as well as the state of the adjoint variables. Details on how the adjoint variables are implemented are abstracted away by this interface.
The adjoint variables can be read and written, resized, zeroed, and swapped. The number of adjoint variables can be queried, and, if applicable, a raw pointer to an underlying array implementation can be obtained.
The set of adjoint variables can be "in use" or "not in use". The adjoint variables are "in use" whenever there is read or write access to adjoint variables, or when any general property of the set of adjoint variables such as size is queried. The implementations of this interface ensure mutual exclusion between the "in use" state and reallocations of the set of adjoint variables due to resizing. Resizing is only allowed if the adjoint variables are "not in use". The implementations of data() and size() are expected to declare usage internally, if needed. For performance reasons, the operator[]() accessors and zeroAll() don't declare usage internally. Instead, the tape is responsible for this. It should declare usage by calls to beginUse() and endUse(). This way, multiple such calls can be safeguarded by a single usage declaration.
The tape must not call resize() as long as it has declared usage.
To give an example, tape evaluation involves multiple operator[]() calls. Prior to the evaluation, the tape ensures that the set of adjoint variables is sufficiently large. It calls beginUse() before the evaluation and endUse() after it. During the evaluation, no further resizing of the set of adjoint variables takes place.
See codi::DataManagementTapeInterface for a multithreading perspective on the "in use" mechanism.
A tape that maintains its adjoints internally against this interface can easily exchange the adjoint implementation. The principle use case of this interface is, at the moment, replacing a classical, tape-local adjoint vector by a thread-safe global one for use in a shared-memory parallel setting, see LocalAdjoints and ThreadSafeGlobalAdjoints.
T_Gradient | The gradient type of a tape, usually chosen as ActiveType::Gradient. |
T_Identifier | The adjoint/tangent identification of a tape, usually chosen as ActiveType::Identifier. |
T_Tape | The associated tape type. |
|
inline |
Constructor
initialSize | Initial number of adjoint variables. |