Skip to content

Commit 8b52502

Browse files
BP5+groupbased: allow only up to 100 steps (#1732)
* BP5+groupbased: allow only up to 1000 steps * Configure this via env variable OPENPMD_BP5_GROUPENCODING_MAX_STEPS=1000 * Add documentation * Lower limit to 100
1 parent bea91a4 commit 8b52502

3 files changed

Lines changed: 99 additions & 17 deletions

File tree

docs/source/backends/adios2.rst

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,24 @@ The ADIOS2 SST engine for streaming can be picked by specifying the ending ``.ss
7575
The following environment variables control ADIOS2 I/O behavior at runtime.
7676
Fine-tuning these is especially useful when running at large scale.
7777

78-
===================================== ========== ================================================================================
79-
environment variable default description
80-
===================================== ========== ================================================================================
81-
``OPENPMD_ADIOS2_HAVE_PROFILING`` ``1`` Turns on/off profiling information right after a run.
82-
``OPENPMD_ADIOS2_HAVE_METADATA_FILE`` ``1`` Online creation of the adios journal file (``1``: yes, ``0``: no).
83-
``OPENPMD_ADIOS2_NUM_SUBSTREAMS`` ``0`` Number of files to be created, 0 indicates maximum number possible.
84-
``OPENPMD_ADIOS2_ENGINE`` ``File`` `ADIOS2 engine <https://adios2.readthedocs.io/en/latest/engines/engines.html>`_
85-
``OPENPMD_ADIOS2_PRETEND_ENGINE`` *empty* Pretend that an (unknown) ADIOS2 engine is in fact another one (also see the ``adios2.pretend_engine`` :ref:`parameter <backendconfig-adios2>`).
86-
``OPENPMD2_ADIOS2_USE_GROUP_TABLE`` ``0`` Use group table (see below)
87-
``OPENPMD_ADIOS2_STATS_LEVEL`` ``0`` whether to generate statistics for variables in ADIOS2. (``1``: yes, ``0``: no).
88-
``OPENPMD_ADIOS2_ASYNC_WRITE`` ``0`` ADIOS2 BP5 engine: 1 means setting "AsyncWrite" in ADIOS2 to "on". Flushes will go to the buffer by default (see ``preferred_flush_target``).
89-
``OPENPMD_ADIOS2_BP5_BufferChunkMB`` ``0`` ADIOS2 BP5 engine: applies when using either EveryoneWrites or EveryoneWritesSerial aggregation
90-
``OPENPMD_ADIOS2_BP5_MaxShmMB`` ``0`` ADIOS2 BP5 engine: applies when using TwoLevelShm aggregation
91-
``OPENPMD_ADIOS2_BP5_NumSubFiles`` ``0`` ADIOS2 BP5 engine: num of subfiles
92-
``OPENPMD_ADIOS2_BP5_NumAgg`` ``0`` ADIOS2 BP5 engine: num of aggregators
93-
``OPENPMD_ADIOS2_BP5_TypeAgg`` *empty* ADIOS2 BP5 engine: aggregation type. (EveryoneWrites, EveryoneWritesSerial, TwoLevelShm)
94-
===================================== ========== ================================================================================
78+
======================================= ========== ================================================================================
79+
environment variable default description
80+
======================================= ========== ================================================================================
81+
``OPENPMD_ADIOS2_HAVE_PROFILING`` ``1`` Turns on/off profiling information right after a run.
82+
``OPENPMD_ADIOS2_HAVE_METADATA_FILE`` ``1`` Online creation of the adios journal file (``1``: yes, ``0``: no).
83+
``OPENPMD_ADIOS2_NUM_SUBSTREAMS`` ``0`` Number of files to be created, 0 indicates maximum number possible.
84+
``OPENPMD_ADIOS2_ENGINE`` ``File`` `ADIOS2 engine <https://adios2.readthedocs.io/en/latest/engines/engines.html>`_
85+
``OPENPMD_ADIOS2_PRETEND_ENGINE`` *empty* Pretend that an (unknown) ADIOS2 engine is in fact another one (also see the ``adios2.pretend_engine`` :ref:`parameter <backendconfig-adios2>`).
86+
``OPENPMD2_ADIOS2_USE_GROUP_TABLE`` ``0`` Use group table (see below)
87+
``OPENPMD_ADIOS2_STATS_LEVEL`` ``0`` whether to generate statistics for variables in ADIOS2. (``1``: yes, ``0``: no).
88+
``OPENPMD_ADIOS2_ASYNC_WRITE`` ``0`` ADIOS2 BP5 engine: 1 means setting "AsyncWrite" in ADIOS2 to "on". Flushes will go to the buffer by default (see ``preferred_flush_target``).
89+
``OPENPMD_ADIOS2_BP5_BufferChunkMB`` ``0`` ADIOS2 BP5 engine: applies when using either EveryoneWrites or EveryoneWritesSerial aggregation
90+
``OPENPMD_ADIOS2_BP5_MaxShmMB`` ``0`` ADIOS2 BP5 engine: applies when using TwoLevelShm aggregation
91+
``OPENPMD_ADIOS2_BP5_NumSubFiles`` ``0`` ADIOS2 BP5 engine: num of subfiles
92+
``OPENPMD_ADIOS2_BP5_NumAgg`` ``0`` ADIOS2 BP5 engine: num of aggregators
93+
``OPENPMD_ADIOS2_BP5_TypeAgg`` *empty* ADIOS2 BP5 engine: aggregation type. (EveryoneWrites, EveryoneWritesSerial, TwoLevelShm)
94+
``OPENPMD_BP5_GROUPENCODING_MAX_STEPS`` ``100`` ADIOS2 BP5 engine: max number of allowed output steps in group encoding.
95+
======================================= ========== ================================================================================
9596

9697
Please refer to the `ADIOS2 documentation <https://adios2.readthedocs.io/en/latest/engines/engines.html>`_ for details on I/O tuning.
9798

@@ -312,6 +313,21 @@ Rather than by reallocation as in BP4, this is done by appending a new chunk, le
312313
The default is to flush to disk (except when specifying ``OPENPMD_ADIOS2_ASYNC_WRITE=1``), but the default ``preferred_flush_target`` can also be specified via JSON/TOML at the ``Series`` level.
313314

314315

316+
The BP5 engine is known to perform extremely bad for group-based encoding with many Iterations, since its design assumes that the metadata structure will be constant across output steps, while group-based encoding will add new variables and attributes for each Iteration.
317+
The openPMD-api will hence cancel operation after 100 written Iterations in group-based encoding for BP5.
318+
Experiments with PIConGPU show that the metadata (!) size grows from 10MB to 1GB when going from 100 to 1000 output steps in this setup.
319+
The environment variable ``OPENPMD_BP5_GROUPENCODING_MAX_STEPS`` may be used to change this limit (specifying the limit as ``0`` will disable the check).
320+
321+
For workarounds you may follow these guidelines:
322+
323+
* Use file encoding by including an expansion pattern ``%T`` in the filename.
324+
* If output to a single file is required, then:
325+
326+
* Use another ADIOS2 engine, recommended is the BP4 engine by selecting file ending ``.bp4``.
327+
* Use another openPMD backend, recommended is HDF5 by selecting file ending ``.h5``.
328+
* (experimental) use variable encoding with BP5, either by using the API call ``Series::setIterationEncoding(IterationEncoding::variableBased)`` / ``Series.iteration_encoding = Iteration_Encoding.variable_based`` or by using the JSON/TOML configuration ``{"iteration_encoding": "variable_based"}`` / ``iteration_encoding = "variable_based"``.
329+
Note that there is at this point no complete read support for variable-encoded outputs.
330+
315331

316332

317333
Known Issues

include/openPMD/IO/ADIOS/ADIOS2File.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "openPMD/IO/IOTask.hpp"
2626
#include "openPMD/IO/InvalidatableFile.hpp"
2727
#include "openPMD/config.hpp"
28+
#include <optional>
2829

2930
#if openPMD_HAVE_ADIOS2
3031
#include <adios2.h>
@@ -429,6 +430,7 @@ class ADIOS2File
429430
*/
430431
size_t m_currentStep = 0;
431432
bool useStepSelection = false;
433+
std::optional<size_t> m_max_steps_bp5 = std::make_optional<size_t>(100);
432434

433435
/*
434436
* ADIOS2 does not give direct access to its internal attribute and

src/IO/ADIOS/ADIOS2File.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,70 @@ AdvanceStatus ADIOS2File::advance(AdvanceMode mode)
12411241
case AdvanceMode::BEGINSTEP: {
12421242
adios2::StepStatus adiosStatus{};
12431243

1244+
auto check_bp5 = [&]() -> bool {
1245+
std::string engineType = getEngine().Type();
1246+
std::transform(
1247+
engineType.begin(),
1248+
engineType.end(),
1249+
engineType.begin(),
1250+
[](unsigned char c) { return std::tolower(c); });
1251+
return engineType == "bp5writer";
1252+
};
1253+
1254+
if (this->m_currentStep == 0)
1255+
{
1256+
int max_steps_from_env =
1257+
auxiliary::getEnvNum("OPENPMD_BP5_GROUPENCODING_MAX_STEPS", -1);
1258+
if (max_steps_from_env == 0)
1259+
{
1260+
m_max_steps_bp5 = std::nullopt;
1261+
}
1262+
else if (max_steps_from_env != -1)
1263+
{
1264+
m_max_steps_bp5 =
1265+
std::make_optional<size_t>(size_t(max_steps_from_env));
1266+
}
1267+
}
1268+
1269+
// Check some conditions on which to now cancel operation due to
1270+
// unwieldy metadata sizes in BP5 with group encoding
1271+
if (this->m_impl->m_handler->m_encoding ==
1272+
IterationEncoding::groupBased &&
1273+
this->m_max_steps_bp5.has_value() &&
1274+
this->m_currentStep >= *this->m_max_steps_bp5 &&
1275+
(this->m_mode == adios2::Mode::Write ||
1276+
this->m_mode == adios2::Mode::Append) &&
1277+
check_bp5())
1278+
{
1279+
throw error::OperationUnsupportedInBackend(
1280+
"ADIOS2",
1281+
R"(
1282+
Trying to create group-based output with more than )" +
1283+
std::to_string(*this->m_max_steps_bp5) +
1284+
R"( steps in BP5 engine.
1285+
As this engine is not adequate for group encoding, this will create immense
1286+
metadata sizes. For more context, check:
1287+
1288+
* https://github.com/openPMD/openPMD-api/discussions/1724
1289+
* https://github.com/openPMD/openPMD-api/issues/1457
1290+
1291+
Since this is likely to create unreadable data due to the sheer amount of
1292+
metadata, we will cancel the writer now.
1293+
Please consider using either of the following instead:
1294+
1295+
* file encoding (by including an expansion pattern %T in the filename)
1296+
* another ADIOS2 engine (e.g. by selecting file extension .bp4)
1297+
* another openPMD backend (e.g. by selecting file extension .h5)
1298+
* (experimental) variable encoding (e.g. by `Series::setIterationEncoding()`
1299+
or by the JSON config {"iteration_encoding": "variable_based"}).
1300+
Note that there is at this point no complete read support for variable-encoded
1301+
outputs.
1302+
1303+
Use the environment variable OPENPMD_BP5_GROUPENCODING_MAX_STEPS to adjust the
1304+
number of allowed steps. Set the value as 0 to disable this check.
1305+
Be aware of the performance implications described above.)");
1306+
}
1307+
12441308
if (streamStatus != StreamStatus::DuringStep)
12451309
{
12461310
adiosStatus = getEngine().BeginStep();

0 commit comments

Comments
 (0)