diff --git a/docs/source/details/backendconfig.rst b/docs/source/details/backendconfig.rst index d1b4c35efc..a2cc6a94e4 100644 --- a/docs/source/details/backendconfig.rst +++ b/docs/source/details/backendconfig.rst @@ -77,6 +77,11 @@ Explanation of the single keys: * ``type`` supported ADIOS operator type, e.g. zfp, sz * ``parameters`` is an associative map of string parameters for the operator (e.g. compression levels) +* ``adios2.use_span_based_put``: The openPMD-api exposes the `span-based Put() API `_ of ADIOS2 via an overload of ``RecordComponent::storeChunk()``. + This API is incompatible with compression operators as described above. + The openPMD-api will automatically use a fallback implementation for the span-based Put() API if any operator is added to a dataset. + This workaround is enabled on a per-dataset level. + The workaround can be completely deactivated by specifying ``{"adios2": {"use_span_based_put": true}}`` or it can alternatively be activated indiscriminately for all datasets by specifying ``{"adios2": {"use_span_based_put": false}}``. Any setting specified under ``adios2.dataset`` is applicable globally as well as on a per-dataset level. Any setting under ``adios2.engine`` is applicable globally only. diff --git a/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp b/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp index 2fa295373f..46826fe7d7 100644 --- a/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp +++ b/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp @@ -236,6 +236,15 @@ class ADIOS2IOHandlerImpl std::string m_engineType; ADIOS2Schema::schema_t m_schema = ADIOS2Schema::schema_0000_00_00; + enum class UseSpan : char + { + Yes, + No, + Auto + }; + + UseSpan m_useSpanBasedPutByDefault = UseSpan::Auto; + enum class AttributeLayout : char { ByAdiosAttributes, diff --git a/src/IO/ADIOS/ADIOS2IOHandler.cpp b/src/IO/ADIOS/ADIOS2IOHandler.cpp index 305ed528f6..04d53249e3 100644 --- a/src/IO/ADIOS/ADIOS2IOHandler.cpp +++ b/src/IO/ADIOS/ADIOS2IOHandler.cpp @@ -132,6 +132,14 @@ ADIOS2IOHandlerImpl::init( nlohmann::json cfg ) m_config[ "schema" ].json().get< ADIOS2Schema::schema_t >(); } + if( m_config.json().contains( "use_span_based_put" ) ) + { + m_useSpanBasedPutByDefault = + m_config[ "use_span_based_put" ].json().get< bool >() + ? UseSpan::Yes + : UseSpan::No; + } + auto engineConfig = config( ADIOS2Defaults::str_engine ); if( !engineConfig.json().is_null() ) { @@ -704,6 +712,22 @@ struct GetSpan std::string errorMsg = "ADIOS2: getBufferView()"; }; + +struct HasOperators +{ + template< typename T > + bool operator()( std::string const & name, adios2::IO & IO ) const + { + adios2::Variable< T > variable = IO.InquireVariable< T >( name ); + if( !variable ) + { + return false; + } + return !variable.Operations().empty(); + } + + std::string errorMsg = "ADIOS2: getBufferView()"; +}; } // namespace detail void @@ -721,6 +745,28 @@ ADIOS2IOHandlerImpl::getBufferView( auto file = refreshFileFromParent( writable, /* preferParentFile = */ false ); detail::BufferedActions & ba = getFileData( file, IfFileNotOpen::ThrowError ); + + std::string name = nameOfVariable( writable ); + switch( m_useSpanBasedPutByDefault ) + { + case UseSpan::No: + parameters.out->backendManagedBuffer = false; + return; + case UseSpan::Auto: + { + detail::HasOperators hasOperators; + if( switchAdios2VariableType( + parameters.dtype, hasOperators, name, ba.m_IO ) ) + { + parameters.out->backendManagedBuffer = false; + return; + } + break; + } + case UseSpan::Yes: + break; + } + if( parameters.update ) { detail::I_UpdateSpan &updater = @@ -731,7 +777,6 @@ ADIOS2IOHandlerImpl::getBufferView( else { static detail::GetSpan gs; - std::string name = nameOfVariable( writable ); switchAdios2VariableType( parameters.dtype, gs, this, parameters, ba, name ); } }