Skip to content

Commit

Permalink
Merge pull request #3010 from JasonRuonanWang/mgard
Browse files Browse the repository at this point in the history
Rewrite mgard operator to support CPU-GPU unified mgard-x API
  • Loading branch information
JasonRuonanWang authored Jan 19, 2022
2 parents 3fc2e4b + db8c10a commit 403f9c4
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 102 deletions.
2 changes: 1 addition & 1 deletion cmake/FindMGARD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ if(NOT MGARD_FOUND)
)
endif()

find_path(MGARD_INCLUDE_DIR mgard_api.h ${MGARD_INCLUDE_OPTS})
find_path(MGARD_INCLUDE_DIR mgard/compress_x.hpp ${MGARD_INCLUDE_OPTS})
find_library(MGARD_LIBRARY NAMES mgard ${MGARD_LIBRARY_OPTS})
find_library(ZLIB_LIBRARY NAMES zlib z ${ZLIB_LIBRARY_OPTS})
find_library(ZSTD_LIBRARY NAMES zstd ${ZSTD_LIBRARY_OPTS})
Expand Down
211 changes: 116 additions & 95 deletions source/adios2/operator/compress/CompressMGARD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
*
* CompressMGARD.cpp :
*
* Created on: Aug 3, 2018
* Author: William F Godoy [email protected]
* Created on: Dec 1, 2021
* Author: Jason Wang [email protected]
*/

#include "CompressMGARD.h"
#include "adios2/helper/adiosFunctions.h"
#include <MGARDConfig.h>
#include <cstring>
#include <mgard_api.h>
#include <mgard/MGARDConfig.hpp>
#include <mgard/compress_x.hpp>

namespace adios2
{
Expand All @@ -35,11 +35,19 @@ size_t CompressMGARD::Operate(const char *dataIn, const Dims &blockStart,

MakeCommonHeader(bufferOut, bufferOutOffset, bufferVersion);

const size_t ndims = blockCount.size();
Dims convertedDims = ConvertDims(blockCount, type, 3);

const size_t ndims = convertedDims.size();
if (ndims > 5)
{
helper::Log("Operator", "CompressMGARD", "Operate",
"MGARG only supports up to 5 dimensions",
helper::LogMode::EXCEPTION);
}

// mgard V1 metadata
PutParameter(bufferOut, bufferOutOffset, ndims);
for (const auto &d : blockCount)
for (const auto &d : convertedDims)
{
PutParameter(bufferOut, bufferOutOffset, d);
}
Expand All @@ -52,38 +60,47 @@ size_t CompressMGARD::Operate(const char *dataIn, const Dims &blockStart,
static_cast<uint8_t>(MGARD_VERSION_PATCH));
// mgard V1 metadata end

if (ndims > 3)
// set type
mgard_x::data_type mgardType;
if (type == helper::GetDataType<float>())
{
throw std::invalid_argument("ERROR: ADIOS2 MGARD compression: no more "
"than 3-dimensions is supported.\n");
mgardType = mgard_x::data_type::Float;
}

// set type
int mgardType = -1;
if (type == helper::GetDataType<double>())
else if (type == helper::GetDataType<double>())
{
mgardType = 1;
mgardType = mgard_x::data_type::Double;
}
else if (type == helper::GetDataType<std::complex<float>>())
{
mgardType = mgard_x::data_type::Float;
}
else if (type == helper::GetDataType<std::complex<double>>())
{
mgardType = mgard_x::data_type::Double;
}
else
{
throw std::invalid_argument(
"ERROR: ADIOS2 operator "
"MGARD only supports double precision, in call to Put\n");
helper::Log("Operator", "CompressMGARD", "Operate",
"MGARD only supports float and double types",
helper::LogMode::EXCEPTION);
}
// set type end

int r[3];
r[0] = 1;
r[1] = 1;
r[2] = 1;

for (size_t i = 0; i < ndims; i++)
// set mgard style dim info
mgard_x::DIM mgardDim = ndims;
std::vector<mgard_x::SIZE> mgardCount;
for (const auto &c : convertedDims)
{
r[ndims - i - 1] = static_cast<int>(blockCount[i]);
mgardCount.push_back(c);
}
// set mgard style dim info end

// Parameters
bool hasTolerance = false;
double tolerance, s = 0.0;
double tolerance = 0.0;
double s = 0.0;
auto errorBoundType = mgard_x::error_bound_type::REL;

auto itAccuracy = m_Parameters.find("accuracy");
if (itAccuracy != m_Parameters.end())
{
Expand All @@ -98,63 +115,41 @@ size_t CompressMGARD::Operate(const char *dataIn, const Dims &blockStart,
}
if (!hasTolerance)
{
throw std::invalid_argument("ERROR: missing mandatory parameter "
"tolerance for MGARD compression "
"operator\n");
helper::Log("Operator", "CompressMGARD", "Operate",
"missing mandatory parameter tolerance / accuracy",
helper::LogMode::EXCEPTION);
}
auto itSParameter = m_Parameters.find("s");
if (itSParameter != m_Parameters.end())
{
s = std::stod(itSParameter->second);
}

int sizeOut = 0;
unsigned char *dataOutPtr =
mgard_compress(reinterpret_cast<double *>(const_cast<char *>(dataIn)),
sizeOut, r[0], r[1], r[2], tolerance, s);

std::memcpy(bufferOut + bufferOutOffset, dataOutPtr, sizeOut);
free(dataOutPtr);
dataOutPtr = nullptr;

bufferOutOffset += sizeOut;

return bufferOutOffset;
}

size_t CompressMGARD::InverseOperate(const char *bufferIn, const size_t sizeIn,
char *dataOut)
{
size_t bufferInOffset = 1; // skip operator type
const uint8_t bufferVersion =
GetParameter<uint8_t>(bufferIn, bufferInOffset);
bufferInOffset += 2; // skip two reserved bytes

if (bufferVersion == 1)
auto itMode = m_Parameters.find("mode");
if (itMode != m_Parameters.end())
{
return DecompressV1(bufferIn + bufferInOffset, sizeIn - bufferInOffset,
dataOut);
}
else if (bufferVersion == 2)
{
// TODO: if a Version 2 mgard buffer is being implemented, put it here
// and keep the DecompressV1 routine for backward compatibility
}
else
{
throw("unknown mgard buffer version");
if (itMode->second == "ABS")
{
errorBoundType = mgard_x::error_bound_type::ABS;
}
else if (itMode->second == "REL")
{
errorBoundType = mgard_x::error_bound_type::REL;
}
}

return 0;
}
size_t sizeOut = 0;
void *compressedData = nullptr;
mgard_x::compress(mgardDim, mgardType, mgardCount, tolerance, s,
errorBoundType, dataIn, compressedData, sizeOut, false);
std::memcpy(bufferOut + bufferOutOffset, compressedData, sizeOut);
bufferOutOffset += sizeOut;

bool CompressMGARD::IsDataTypeValid(const DataType type) const
{
if (type == DataType::Double)
if (compressedData)
{
return true;
free(compressedData);
}
return false;

return bufferOutOffset;
}

size_t CompressMGARD::DecompressV1(const char *bufferIn, const size_t sizeIn,
Expand All @@ -181,43 +176,69 @@ size_t CompressMGARD::DecompressV1(const char *bufferIn, const size_t sizeIn,
std::to_string(GetParameter<uint8_t>(bufferIn, bufferInOffset)) +
". Please make sure a compatible version is used for decompression.";

int mgardType = -1;
size_t sizeOut =
helper::GetTotalSize(blockCount, helper::GetDataTypeSize(type));

if (type == helper::GetDataType<double>())
if (type == DataType::FloatComplex || type == DataType::DoubleComplex)
{
mgardType = 1;
sizeOut /= 2;
}
else

try
{
throw std::invalid_argument(
"ERROR: ADIOS2 operator "
"MGARD only supports double precision, in call to Get\n");
void *dataOutVoid = nullptr;
mgard_x::decompress(bufferIn + bufferInOffset, sizeIn - bufferInOffset,
dataOutVoid, false);
std::memcpy(dataOut, dataOutVoid, sizeOut);
if (dataOutVoid)
{
free(dataOutVoid);
}
}

int r[3];
r[0] = 1;
r[1] = 1;
r[2] = 1;

for (size_t i = 0; i < ndims; i++)
catch (...)
{
r[ndims - i - 1] = static_cast<int>(blockCount[i]);
helper::Log("Operator", "CompressMGARD", "DecompressV1", m_VersionInfo,
helper::LogMode::EXCEPTION);
}

void *dataPtr = mgard_decompress(
reinterpret_cast<unsigned char *>(
const_cast<char *>(bufferIn + bufferInOffset)),
static_cast<int>(sizeIn - bufferInOffset), r[0], r[1], r[2], 0.0);
return sizeOut;
}

const size_t sizeOut =
helper::GetTotalSize(blockCount, helper::GetDataTypeSize(type));
size_t CompressMGARD::InverseOperate(const char *bufferIn, const size_t sizeIn,
char *dataOut)
{
size_t bufferInOffset = 1; // skip operator type
const uint8_t bufferVersion =
GetParameter<uint8_t>(bufferIn, bufferInOffset);
bufferInOffset += 2; // skip two reserved bytes

std::memcpy(dataOut, dataPtr, sizeOut);
if (bufferVersion == 1)
{
return DecompressV1(bufferIn + bufferInOffset, sizeIn - bufferInOffset,
dataOut);
}
else if (bufferVersion == 2)
{
// TODO: if a Version 2 mgard buffer is being implemented, put it here
// and keep the DecompressV1 routine for backward compatibility
}
else
{
helper::Log("Operator", "CompressMGARD", "DecompressV1",
"unknown mgard buffer version", helper::LogMode::EXCEPTION);
}

free(dataPtr);
dataPtr = nullptr;
return 0;
}

return sizeOut;
bool CompressMGARD::IsDataTypeValid(const DataType type) const
{
if (type == DataType::Double || type == DataType::Float ||
type == DataType::DoubleComplex || type == DataType::FloatComplex)
{
return true;
}
return false;
}

} // end namespace compress
Expand Down
7 changes: 2 additions & 5 deletions source/adios2/operator/compress/CompressMGARD.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
*
* CompressMGARD.h :
*
* Created on: Aug 3, 2018
* Author: William F Godoy [email protected]
* Created on: Dec 1, 2021
* Author: Jason Wang [email protected]
*/

#ifndef ADIOS2_OPERATOR_COMPRESS_COMPRESSMGARD_H_
Expand All @@ -24,9 +24,6 @@ class CompressMGARD : public Operator
{

public:
/**
* Unique constructor
*/
CompressMGARD(const Params &parameters);

~CompressMGARD() = default;
Expand Down
1 change: 0 additions & 1 deletion source/adios2/operator/compress/CompressZFP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ size_t CompressZFP::Operate(const char *dataIn, const Dims &blockStart,
const Dims &blockCount, const DataType type,
char *bufferOut)
{

const uint8_t bufferVersion = 1;
size_t bufferOutOffset = 0;

Expand Down

0 comments on commit 403f9c4

Please sign in to comment.