1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
**
IO
**
The ``IO`` component is the connection between how applications set up their input/output options by selecting an ``Engine`` and its specific parameters, subscribing variables to data, and setting supported transport modes to a particular ``Engine``.
Think of ``IO`` as a control panel for all the user-defined parameters that applications would like to fine tune.
None of the ``IO`` operations are heavyweight until the ``Open`` function that generates an ``Engine`` is called.
Its API allows
* generation of ``Variable`` and ``Attribute`` components containing information about the data in the input output process
* setting ``Engine``-specific parameters and adding supported modes of transport
* generation of ``Engine`` objects to execute the actual IO tasks.
.. note::
If two different engine types are needed (*e.g.* ``BPFile``, ``SST``), you must define two ``IO`` objects.
Also, at reading always define separate IOs to avoid ``Variable`` name clashes.
.. blockdiag::
diagram {
default_fontsize = 17;
default_shape = roundedbox;
default_linecolor = blue;
span_width = 220;
IO -> Var_1, B, Var_N [label = "DefineVariable<T>",fontsize = 13];
B [shape = "dots"];
IO -> B [style = "none"];
IO -> Att_1, C, Att_N [label = "DefineAttribute<T>",fontsize = 13];
C [shape = "dots"];
IO -> C [style = "none"];
IO -> Transport_1, D, Transport_N [label = "AddTransport",fontsize = 13];
D [shape = "dots"];
IO -> D [style = "none"];
IO -> Engine_1, E, Engine_N [label = "Open",fontsize = 13];
E [shape = "dots"];
IO -> E [style = "none"];
}
Setting a Particular Engine and its Parameters
----------------------------------------------
Engines execute the heavy operations in ADIOS2.
Each ``IO`` may select a type of ``Engine`` through the ``SetEngine`` function.
If ``SetEngine`` is not called, then the ``BPFile`` engine is used.
.. code-block:: c++
/** Signature */
void adios2::IO::SetEngine( const std::string engineType );
/** Example */
bpIO.SetEngine("BPFile");
Each ``Engine`` allows the user to fine tune execution of buffering and output tasks via parameters passed to the ``IO`` object.
These parameters are then propagated to the ``Engine``.
For a list of parameters allowed by each engine see :ref:`Available Engines`.
.. note::
``adios2::Params`` is an alias to ``std::map<std::string,std::string>`` to pass parameters as key-value string pairs, which can be initialized with curly-brace initializer lists.
.. code-block:: c++
/** Signature */
/** Passing several parameters at once */
void SetParameters(const adios2:Params& parameters);
/** Passing one parameter key-value pair at a time */
void SetParameter(const std::string key, const std::string value);
/** Examples */
io.SetParameters( { {"Threads", "4"},
{"ProfilingUnits", "Milliseconds"},
{"MaxBufferSize","2Gb"},
{"BufferGrowthFactor", "1.5" }
{"FlushStepsCount", "5" }
} );
io.SetParameter( "Threads", "4" );
Adding Supported Transports with Parameters
-------------------------------------------
The ``AddTransport`` function allows the user to specify how data is moved through the system, *e.g.* RDMA, wide-area networks, or files.
It returns an ``unsigned int`` handler for each transport that can be used with the ``Engine::Close`` function at different times.
``AddTransport`` must provide library specific settings that the low-level system library interface allows.
.. code-block:: c++
/** Signature */
unsigned int AddTransport( const std::string transportType,
const adios2::Params& parameters );
/** Examples */
const unsigned int file1 = io.AddTransport( "File",
{ {"Library", "fstream"},
{"Name","file1.bp" }
} );
const unsigned int file2 = io.AddTransport( "File",
{ {"Library", "POSIX"},
{"Name","file2.bp" }
} );
const unsigned int wan = io.AddTransport( "WAN",
{ {"Library", "Zmq"},
{"IP","127.0.0.1" },
{"Port","80"}
} );
Defining, Inquiring and Removing Variables and Attributes
---------------------------------------------------------
The template functions ``DefineVariable<T>`` allows subscribing to data into ADIOS2 by returning a reference to a ``Variable`` class object whose scope is the same as the ``IO`` object that created it.
The user must provide a unique name, the dimensions: MPI global: shape, MPI local: start and offset, optionally a flag indicating that dimensions are known to be constant, and a data pointer if defined in the application.
Note: data is not passed at this stage.
This is done by the ``Engine`` functions ``Put`` and ``Get`` for Variables.
See the :ref:`Variable` section for supported types and shapes.
.. tip::
``adios2::Dims`` is an alias to ``std::vector<std::size_t>``, while ``adios2::ConstantDims`` is an alias to bool ``true``. Use them for code clarity.
.. code-block:: c++
/** Signature */
adios2::Variable<T>
DefineVariable<T>(const std::string name,
const adios2::Dims &shape = {}, // Shape of global object
const adios2::Dims &start = {}, // Where to begin writing
const adios2::Dims &count = {}, // Where to end writing
const bool constantDims = false);
/** Example */
/** global array of floats with constant dimensions */
adios2::Variable<float> varFloats =
io.DefineVariable<float>("bpFloats",
{size * Nx},
{rank * Nx},
{Nx},
adios2::ConstantDims);
Attributes are extra-information associated with the current ``IO`` object.
The function ``DefineAttribute<T>`` allows for defining single value and array attributes.
Keep in mind that Attributes apply to all Engines created by the ``IO`` object and, unlike Variables which are passed to each ``Engine`` explicitly, their definition contains their actual data.
.. code-block:: c++
/** Signatures */
/** Single value */
adios2::Attribute<T> DefineAttribute(const std::string &name,
const T &value);
/** Arrays */
adios2::Attribute<T> DefineAttribute(const std::string &name,
const T *array,
const size_t elements);
In situations in which a variable and attribute has been previously defined:
1) a variable/attribute reference goes out of scope, or 2) when reading from an incoming stream, the ``IO`` can inquire about the status of variables and attributes.
If the inquired variable/attribute is not found, then the overloaded ``bool()`` operator of returns ``false``.
.. code-block:: c++
/** Signature */
adios2::Variable<T> InquireVariable<T>(const std::string &name) noexcept;
adios2::Attribute<T> InquireAttribute<T>(const std::string &name) noexcept;
/** Example */
adios2::Variable<float> varPressure = io.InquireVariable<float>("pressure");
if( varPressure ) // it exists
{
...
}
.. note::
``adios2::Variable`` overloads ``operator bool()`` so that we can check for invalid states (e.g. variables haven't arrived in a stream, weren't previously defined, or weren't written in a file).
.. caution::
Since ``InquireVariable`` and ``InquireAttribute`` are template functions, both the name and type must match the data you are looking for.
Opening an Engine
-----------------
The ``IO::Open`` function creates a new derived object of the abstract ``Engine`` class and returns a reference handler to the user.
A particular ``Engine`` type is set to the current ``IO`` component with the ``IO::SetEngine`` function.
Engine polymorphism is handled internally by the ``IO`` class, which allows subclassing future derived ``Engine`` types without changing the basic API.
``Engine`` objects are created in various modes.
The available modes are ``adios2::Mode::Read``, ``adios2::Mode::ReadRandomAccess``, ``adios2::Mode::Write``, ``adios2::Mode::Append``, ``adios2::Mode::Sync``, ``adios2::Mode::Deferred``, and ``adios2::Mode::Undefined``.
.. code-block:: c++
/** Signatures */
/** Provide a new MPI communicator other than from ADIOS->IO->Engine */
adios2::Engine adios2::IO::Open(const std::string &name,
const adios2::Mode mode,
MPI_Comm mpiComm );
/** Reuse the MPI communicator from ADIOS->IO->Engine \n or non-MPI serial mode */
adios2::Engine adios2::IO::Open(const std::string &name,
const adios2::Mode mode);
/** Examples */
/** Engine derived class, spawned to start Write operations */
adios2::Engine bpWriter = io.Open("myVector.bp", adios2::Mode::Write);
/** Engine derived class, spawned to start Read operations on rank 0 */
if( rank == 0 )
{
adios2::Engine bpReader = io.Open("myVector.bp",
adios2::Mode::Read,
MPI_COMM_SELF);
}
.. caution::
Always pass ``MPI_COMM_SELF`` if an ``Engine`` lives in only one MPI process.
``Open`` and ``Close`` are collective operations.
|