Skip to content

Commit

Permalink
New operator MDR, for refactoring floating point arrays using MGARD's…
Browse files Browse the repository at this point in the history
… new MDR extension. (#3826)

- Only works with BP5 for now since BP5 deserializer had to be modified for reading with accuracy
 - Use mgard cmake flag MGARD_ENABLE_MDR to set ADIOS2_HAVE_MGARD_MDR flag and build refactor operator conditionally
 - Added Accuracy struct to adios types (error, norm, and rel|abs flag)
 - Set/GetAccuracy() functions to Variable, VariableBase and Operator classes.
 - BP5 deserializer now prepares the operator with accuracy before calling Decompress().
 - bpls new option --error "double,double|inf,rel|abs" added.
 - Add tests for MDR operator and Accuracy default behavior (for all operators)
 - Add rounding error constants adios2::ops::mdr::DOUBLE_ROUNDING_ERROR_LIMIT and FLOAT_ROUNDING_ERROR_LIMIT,
      beacuse GetAccuracy() is limited by rounding errors in MDR
  • Loading branch information
pnorbert committed Dec 12, 2023
1 parent 53235b3 commit 931941e
Show file tree
Hide file tree
Showing 25 changed files with 1,257 additions and 8 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ endif()

set(ADIOS2_CONFIG_OPTS
DataMan DataSpaces HDF5 HDF5_VOL MHS SST Fortran MPI Python Blosc2 BZip2
LIBPRESSIO MGARD PNG SZ ZFP DAOS IME O_DIRECT Sodium Catalyst SysVShMem UCX
LIBPRESSIO MGARD MGARD_MDR PNG SZ ZFP DAOS IME O_DIRECT Sodium Catalyst SysVShMem UCX
ZeroMQ Profiling Endian_Reverse Derived_Variable AWSSDK GPU_Support CUDA Kokkos
Kokkos_CUDA Kokkos_HIP Kokkos_SYCL
)
Expand Down
14 changes: 14 additions & 0 deletions bindings/CXX11/adios2/cxx11/Variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ namespace adios2
} \
\
template <> \
void Variable<T>::SetAccuracy(const adios2::Accuracy &a) \
{ \
helper::CheckForNullptr(m_Variable, "in call to Variable<T>::SetAccuracy"); \
m_Variable->SetAccuracy(a); \
} \
\
template <> \
size_t Variable<T>::SelectionSize() const \
{ \
helper::CheckForNullptr(m_Variable, "in call to Variable<T>::SelectionSize"); \
Expand Down Expand Up @@ -219,6 +226,13 @@ namespace adios2
} \
\
template <> \
adios2::Accuracy Variable<T>::GetAccuracy() \
{ \
helper::CheckForNullptr(m_Variable, "in call to Variable<T>::GetAccuracy"); \
return m_Variable->GetAccuracy(); \
} \
\
template <> \
std::vector<std::vector<typename Variable<T>::Info>> Variable<T>::AllStepsBlocksInfo() \
{ \
return DoAllStepsBlocksInfo(); \
Expand Down
13 changes: 13 additions & 0 deletions bindings/CXX11/adios2/cxx11/Variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ class Variable
*/
void SetStepSelection(const adios2::Box<size_t> &stepSelection);

/**
* Sets the requested accuracy for the next read operation.
* The actual accuracy after the read is provided in GetAccuracy()
*/
void SetAccuracy(const adios2::Accuracy &a);

/**
* Returns the number of elements required for pre-allocation based on
* current count and stepsCount
Expand Down Expand Up @@ -335,6 +341,13 @@ class Variable
*/
T Max(const size_t step = adios2::DefaultSizeT) const;

/**
* Get the provided accuracy for the last read operation.
* Most operations provide data as it was written, meaning that
* error is reported as 0.0
*/
adios2::Accuracy GetAccuracy();

/** Contains block information for a particular Variable<T> */
struct Info
{
Expand Down
4 changes: 4 additions & 0 deletions cmake/DetectOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,17 @@ if(TARGET LibPressio::libpressio)
endif()

# MGARD
set(ADIOS2_HAVE_MGARD_MDR FALSE)
if(ADIOS2_USE_MGARD STREQUAL AUTO)
find_package(mgard CONFIG)
elseif(ADIOS2_USE_MGARD)
find_package(mgard REQUIRED CONFIG)
endif()
if(mgard_FOUND)
set(ADIOS2_HAVE_MGARD TRUE)
if(MGARD_ENABLE_MDR)
set(ADIOS2_HAVE_MGARD_MDR TRUE)
endif()
endif()

# PNG
Expand Down
7 changes: 5 additions & 2 deletions examples/basics/globalArrayND/globalArrayNDWrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ int main(int argc, char *argv[])
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
#endif
const int NSTEPS = 5;
const int NSTEPS = 1;

#if ADIOS2_USE_MPI
adios2::ADIOS adios(MPI_COMM_WORLD);
Expand All @@ -58,7 +58,7 @@ int main(int argc, char *argv[])
#endif

// Application variables for output
const unsigned int Nx = 10;
const unsigned int Nx = 100000;
// Global 2D array, size of nproc x Nx, with 1D decomposition
// Each process writes one "row" of the 2D matrix.
std::vector<double> row(Nx);
Expand All @@ -84,6 +84,9 @@ int main(int argc, char *argv[])

io.DefineAttribute<int>("nsteps", NSTEPS);

adios2::Operator op = adios.DefineOperator("mdr", "mdr");
varGlobalArray.AddOperation(op, {{"accuracy", std::to_string(0.1)}});

// Open file. "w" means we overwrite any existing file on disk,
// but Advance() will append steps to the same file.
adios2::Engine writer = io.Open("globalArray.bp", adios2::Mode::Write);
Expand Down
3 changes: 3 additions & 0 deletions source/adios2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ endif()
if(ADIOS2_HAVE_MGARD)
target_sources(adios2_core PRIVATE operator/compress/CompressMGARDPlus.cpp)
target_sources(adios2_core PRIVATE operator/compress/CompressMGARD.cpp)
if(ADIOS2_HAVE_MGARD_MDR)
target_sources(adios2_core PRIVATE operator/refactor/RefactorMDR.cpp)
endif()
target_link_libraries(adios2_core PRIVATE mgard::mgard)
endif()

Expand Down
29 changes: 29 additions & 0 deletions source/adios2/common/ADIOSTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,22 @@ using Box = std::pair<T, T>;
template <typename T, typename Enable = void>
struct TypeInfo;

/** Data accuracy **/

/* Error. Accuracy can be requested for reading data.
norm: 0.0 = L2, inf() = Linf
relative: true = relative error, false = absolute error
*/
struct Accuracy
{
double error;
double norm;
bool relative;
};

constexpr double L2_norm = 0.0;
constexpr double Linf_norm = std::numeric_limits<double>::infinity();

/**
* Return the actual size in bytes of elements of the given type. Returns -1
* for strings.
Expand Down Expand Up @@ -405,6 +421,19 @@ constexpr char s[] = "s";
}
#endif

#ifdef ADIOS2_HAVE_MGARD_MDR

constexpr char MDR[] = "mdr";

namespace mdr
{
constexpr double DOUBLE_ROUNDING_ERROR_LIMIT = 5.0e-16;
constexpr double FLOAT_ROUNDING_ERROR_LIMIT = 3.0e-7;
namespace key
{}
}
#endif

#ifdef ADIOS2_HAVE_LIBPRESSIO
constexpr char LossyLIBPRESSIO[] = "libpressio";
namespace libpressio
Expand Down
3 changes: 3 additions & 0 deletions source/adios2/core/Info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ static const char *const operators[] = {
"MGARD",
"MGARDPlus",
#endif
#ifdef ADIOS2_HAVE_MGARD_MDR
"MDR",
#endif
#ifdef ADIOS2_HAVE_SZ
"SZ",
#endif
Expand Down
11 changes: 11 additions & 0 deletions source/adios2/core/Operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "Operator.h"
#include "adios2/helper/adiosFunctions.h"

#include <iostream>

namespace adios2
{
namespace core
Expand All @@ -30,6 +32,9 @@ void Operator::SetParameter(const std::string key, const std::string value) noex

Params &Operator::GetParameters() noexcept { return m_Parameters; }

void Operator::SetAccuracy(const adios2::Accuracy &a) noexcept { m_AccuracyRequested = a; }
adios2::Accuracy Operator::GetAccuracy() const noexcept { return m_AccuracyProvided; }

#define declare_type(T) \
\
void Operator::RunCallback1(const T *arg0, const std::string &arg1, const std::string &arg2, \
Expand Down Expand Up @@ -96,6 +101,12 @@ Dims Operator::ConvertDims(const Dims &dimensions, const DataType type, const si

size_t Operator::GetHeaderSize() const { return 0; }

size_t Operator::GetEstimatedSize(const size_t ElemCount, const size_t ElemSize, const size_t ndims,
const size_t *dims) const
{
return ElemCount * ElemSize + 128;
};

// PRIVATE
void Operator::CheckCallbackType(const std::string type) const
{
Expand Down
13 changes: 13 additions & 0 deletions source/adios2/core/Operator.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Operator
COMPRESS_SZ = 6,
COMPRESS_ZFP = 7,
COMPRESS_MGARDPLUS = 8,
REFACTOR_MDR = 41,
CALLBACK_SIGNATURE1 = 51,
CALLBACK_SIGNATURE2 = 52,
PLUGIN_INTERFACE = 53,
Expand All @@ -56,6 +57,9 @@ class Operator

Params &GetParameters() noexcept;

void SetAccuracy(const adios2::Accuracy &a) noexcept;
adios2::Accuracy GetAccuracy() const noexcept;

#define declare_type(T) \
virtual void RunCallback1(const T *, const std::string &, const std::string &, \
const std::string &, const size_t, const Dims &, const Dims &, \
Expand All @@ -68,6 +72,10 @@ class Operator

virtual size_t GetHeaderSize() const;

/** Give an upper bound estimate how big the transformed data could be */
virtual size_t GetEstimatedSize(const size_t ElemCount, const size_t ElemSize,
const size_t ndims, const size_t *dims) const;

/**
* @param dataIn
* @param blockStart
Expand All @@ -94,6 +102,11 @@ class Operator
/** Parameters associated with a particular Operator */
Params m_Parameters;

/** user requested accuracy */
Accuracy m_AccuracyRequested = {0.0, 0.0, false};
/** provided accuracy */
Accuracy m_AccuracyProvided = {0.0, 0.0, false};

/**
* Used by lossy compressors with a limitation on complex data types or
* dimentions Returns a adios2::Dims object that meets the requirement of a
Expand Down
8 changes: 8 additions & 0 deletions source/adios2/core/VariableBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ void VariableBase::SetMemorySelection(const Box<Dims> &memorySelection)
m_MemoryCount = memorySelection.second;
}

void VariableBase::SetAccuracy(const adios2::Accuracy &a) noexcept
{
m_AccuracyRequested = a;
m_AccuracyProvided = {0.0, a.norm, a.relative};
}
adios2::Accuracy VariableBase::GetAccuracy() const noexcept { return m_AccuracyProvided; }
adios2::Accuracy VariableBase::GetAccuracyRequested() const noexcept { return m_AccuracyRequested; }

size_t VariableBase::GetAvailableStepsStart() const { return m_AvailableStepsStart; }

size_t VariableBase::GetAvailableStepsCount() const { return m_AvailableStepsCount; }
Expand Down
21 changes: 21 additions & 0 deletions source/adios2/core/VariableBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ class VariableBase

Engine *m_Engine = nullptr;

/** user requested accuracy */
Accuracy m_AccuracyRequested = {0.0, 0.0, false};
/** provided accuracy */
Accuracy m_AccuracyProvided = {0.0, 0.0, false};

/** Index to Step and blocks' (inside a step) characteristics position in a
* serial metadata buffer
* <pre>
Expand Down Expand Up @@ -166,6 +171,22 @@ class VariableBase
*/
void SetMemorySelection(const Box<Dims> &memorySelection);

/**
* Sets the requested accuracy for the next read operation.
* The actual accuracy after the read is provided in GetAccuracy()
*/
void SetAccuracy(const adios2::Accuracy &a) noexcept;

/**
* Get the provided accuracy for the last read operation.
* Most operations provide data as it was written, meaning that
* error is reported as 0.0
*/
adios2::Accuracy GetAccuracy() const noexcept;

/** Return the requested accuracy set by user with SetAccuracy */
adios2::Accuracy GetAccuracyRequested() const noexcept;

size_t GetAvailableStepsStart() const;

size_t GetAvailableStepsCount() const;
Expand Down
12 changes: 12 additions & 0 deletions source/adios2/operator/OperatorFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#include "adios2/operator/compress/CompressMGARDPlus.h"
#endif

#ifdef ADIOS2_HAVE_MGARD_MDR
#include "adios2/operator/refactor/RefactorMDR.h"
#endif

#ifdef ADIOS2_HAVE_PNG
#include "adios2/operator/compress/CompressPNG.h"
#endif
Expand Down Expand Up @@ -74,6 +78,8 @@ std::string OperatorTypeToString(const Operator::OperatorType type)
return "sz";
case Operator::COMPRESS_ZFP:
return "zfp";
case Operator::REFACTOR_MDR:
return "mdr";
case Operator::PLUGIN_INTERFACE:
return "plugin";
default:
Expand Down Expand Up @@ -139,6 +145,12 @@ std::shared_ptr<Operator> MakeOperator(const std::string &type, const Params &pa
{
#ifdef ADIOS2_HAVE_ZFP
ret = std::make_shared<compress::CompressZFP>(parameters);
#endif
}
else if (typeLowerCase == "mdr")
{
#ifdef ADIOS2_HAVE_MGARD_MDR
ret = std::make_shared<refactor::RefactorMDR>(parameters);
#endif
}
else if (typeLowerCase == "plugin")
Expand Down
2 changes: 2 additions & 0 deletions source/adios2/operator/OperatorFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace adios2
namespace core
{

std::string OperatorTypeToString(const Operator::OperatorType type);

std::shared_ptr<Operator> MakeOperator(const std::string &type, const Params &parameters);

size_t Decompress(const char *bufferIn, const size_t sizeIn, char *dataOut, MemorySpace memSpace,
Expand Down

0 comments on commit 931941e

Please sign in to comment.