Skip to content

Commit

Permalink
libpressio version 0.61.0
Browse files Browse the repository at this point in the history
Major Changes

+ new autocorr and diff_pdf metrics modules to compute the 1d
  autocorrelation of the errors and the distributions of the differences
  respectively
+ added new pkg-config for libpressio_cxx that depends on std_compat_cxx
  to make it easier to develop compressor modules without cmake

Minor Changes

+ allow more moves for options for performance

Bug Fixes

+ correct incorrect forward declarations in the JSON modules that could
  cause ABI failures
+ throw an error instead of returning a deceptive nullptr in external
  metrics module
+ include missing return for empty options
  • Loading branch information
robertu94 committed Mar 23, 2021
1 parent f506e2e commit 17514fd
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,bugprone-*,-bugprone-macro-parentheses,performance-*,portability-*,security-*,moderize*,-clang-analyzer-optin.portability.UnixAPI'
Checks: 'clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,bugprone-*,-bugprone-macro-parentheses,performance-*,portability-*,security-*,moderize*,-clang-analyzer-optin.portability.UnixAPI,-clang-analyzer-optin.mpi.MPI-Checker'
WarningsAsErrors: ''
HeaderFilterRegex: '(\./include.*)|(.*presio.*)'
AnalyzeTemporaryDtors: false
Expand Down
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(libpressio VERSION "0.60.0" LANGUAGES CXX C)
project(libpressio VERSION "0.61.0" LANGUAGES CXX C)

#correct was to set a default build type
# https://blog.kitware.com/cmake-and-the-default-build-type/
Expand Down Expand Up @@ -66,6 +66,8 @@ add_library(libpressio
./src/plugins/metrics/kl_divergance.cc
./src/plugins/metrics/printer.cc
./src/plugins/metrics/region_of_interest.cc
./src/plugins/metrics/diff_pdf.cc
./src/plugins/metrics/autocorr.cc
./src/plugins/metrics/noop.cc
./src/plugins/io/copy_template.cc
./src/plugins/io/posix.cc
Expand Down Expand Up @@ -384,6 +386,11 @@ configure_file(
${CMAKE_CURRENT_BINARY_DIR}/libpressio.pc
@ONLY
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/libpressio_cxx.pc.in
${CMAKE_CURRENT_BINARY_DIR}/libpressio_cxx.pc
@ONLY
)
target_sources(libpressio
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/include/pressio_version.h
Expand Down Expand Up @@ -414,6 +421,7 @@ install(EXPORT LibPressioConfig NAMESPACE LibPressio:: DESTINATION share/LibPres
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libpressio)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/pressio_version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libpressio)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpressio.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pkgconfig)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpressio_cxx.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pkgconfig)

if(BUILD_TESTING)
add_subdirectory(test)
Expand Down
6 changes: 3 additions & 3 deletions include/libpressio_ext/cpp/json.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <nlohmann/json_fwd.hpp>
class pressio_data;
class pressio_option;
class pressio_options;
struct pressio_data;
struct pressio_option;
struct pressio_options;

void to_json(nlohmann::json& j, pressio_data const& data);
void to_json(nlohmann::json& j, pressio_option const& option);
Expand Down
14 changes: 13 additions & 1 deletion include/libpressio_ext/cpp/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ struct pressio_option final {
>::type>
pressio_option(compat::optional<T> const& value): option(value) {}

/** constructs an option that holds the specified value
* \param[in] value the value the option is to hold
* */
template<class T, typename = typename std::enable_if<
!std::is_same<T, pressio_conversion_safety>::value &&
!std::is_same<T, pressio_option>::value &&
!std::is_same<T, const char*>::value &&
!std::is_same<T, compat::monostate>::value
>::type>
pressio_option(compat::optional<T> && value): option(value) {}

/** constructs an option that holds the specified value
* \param[in] value the value the option is to hold
* */
Expand All @@ -96,13 +107,14 @@ struct pressio_option final {
>::type>
pressio_option(T const& value): option(compat::optional<T>(value)) {}


/** specialization for option to reset the type to hold no type or value
* \param[in] value the monostate singleton
* */
pressio_option(compat::monostate value): option(value) { }

/** specialization for strings to be compatable with c++11
* \param[in] value the monostate singleton
* \param[in] value the string value to construct
* */
pressio_option(const char* value): option(std::string(value)) { }

Expand Down
9 changes: 9 additions & 0 deletions libpressio_cxx.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@/libpressio
libdir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@

Name: Libpressio
Description: An abstraction between different pressio compressors
Version: @PROJECT_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -llibpressio
Requires: std_compat_cxx
165 changes: 165 additions & 0 deletions src/plugins/metrics/autocorr.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include <cmath>
#include "pressio_data.h"
#include "pressio_options.h"
#include "libpressio_ext/cpp/data.h"
#include "libpressio_ext/cpp/metrics.h"
#include "libpressio_ext/cpp/options.h"
#include "libpressio_ext/cpp/pressio.h"
#include "std_compat/memory.h"

namespace autocorr {
struct metrics {
pressio_data autocorr;
};
struct compute_metrics{
template <class ForwardIt1, class ForwardIt2>
metrics operator()(ForwardIt1 input_begin, ForwardIt1 input_end, ForwardIt2 input2_begin, ForwardIt2 input2_end) const
{
metrics m;
const size_t num_elements = std::min(input_end - input_begin, input2_end- input2_begin);
if(num_elements == 0) {
return m;
}

std::vector<double> errors(num_elements);

m.autocorr = pressio_data::owning(pressio_double_dtype, {static_cast<size_t>(autocorr_lags + 1)});
double average_error=0;
for (size_t i = 0; i < num_elements; ++i) {
errors[i] = input_begin[i] - input2_begin[i];
average_error += errors[i];
}
average_error /= static_cast<double>(num_elements);
auto autocorr = static_cast<double*>(m.autocorr.data());


if (num_elements > 4096)
{
double cov = 0;
for (size_t i = 0; i < num_elements; i++) {
cov += (errors[i] - average_error)*(errors[i] - average_error);
}

cov = cov/num_elements;

if (cov == 0)
{
for (size_t delta = 1; delta <= autocorr_lags; delta++)
autocorr[delta] = 0;
}
else
{
for(size_t delta = 1; delta <= autocorr_lags; delta++)
{
double sum = 0;

for (size_t i = 0; i < num_elements-delta; i++)
sum += (errors[i]-average_error)*(errors[i+delta]-average_error);

autocorr[delta] = sum/(num_elements-delta)/cov;
}
}
}
else
{
for (size_t delta = 1; delta <= autocorr_lags; delta++)
{
double avg_0 = 0;
double avg_1 = 0;

for (size_t i = 0; i < num_elements-delta; i++)
{
avg_0 += errors[i];
avg_1 += errors[i+delta];
}

avg_0 = avg_0 / (num_elements-delta);
avg_1 = avg_1 / (num_elements-delta);

double cov_0 = 0;
double cov_1 = 0;

for (size_t i = 0; i < num_elements-delta; i++)
{
cov_0 += (errors[i]-avg_0)*(errors[i]-avg_0);
cov_1 += (errors[i+delta]-avg_1)*(errors[i+delta]-avg_1);
}

cov_0 = cov_0/(num_elements-delta);
cov_1 = cov_1/(num_elements-delta);

cov_0 = sqrt(cov_0);
cov_1 = sqrt(cov_1);

if (cov_0*cov_1 == 0)
{
for (delta = 1; delta <= autocorr_lags; delta++)
autocorr[delta] = 1;
}
else
{
double sum = 0;

for (size_t i = 0; i < num_elements-delta; i++)
sum += (errors[i]-avg_0)*(errors[i+delta]-avg_1);

autocorr[delta] = sum/(num_elements-delta)/(cov_0*cov_1);
}
}
}

autocorr[0] = 1;


return m;
}

uint64_t autocorr_lags;
};
}

class autocorr_plugin : public libpressio_metrics_plugin {

public:
void begin_compress(const struct pressio_data * input, struct pressio_data const * ) override {
input_data = pressio_data::clone(*input);
}
void end_decompress(struct pressio_data const*, struct pressio_data const* output, int ) override {
err_metrics = pressio_data_for_each<autocorr::metrics>(input_data, *output, autocorr::compute_metrics{autocorr_lags});
}

int set_options(pressio_options const& opts) override {
get(opts, "autocorr:autocorr_lags", &autocorr_lags);
return 0;
}
pressio_options get_options() const override {
pressio_options opts;
set(opts, "autocorr:autocorr_lags", autocorr_lags);
return opts;
}

struct pressio_options get_metrics_results() const override {
pressio_options opt;
if(err_metrics) {
set(opt, "autocorr:autocorr", err_metrics->autocorr);
} else {
set_type(opt, "autocorr:autocorr", pressio_option_data_type);
}
return opt;
}
std::unique_ptr<libpressio_metrics_plugin> clone() override {
return compat::make_unique<autocorr_plugin>(*this);
}

const char* prefix() const override {
return "autocorr";
}


private:
uint64_t autocorr_lags = 100;
pressio_data input_data = pressio_data::empty(pressio_byte_dtype, {});
compat::optional<autocorr::metrics> err_metrics;
};

static pressio_register metrics_autocorr_plugin(metrics_plugins(), "autocorr", [](){ return compat::make_unique<autocorr_plugin>(); });
105 changes: 105 additions & 0 deletions src/plugins/metrics/diff_pdf.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "pressio_data.h"
#include "pressio_options.h"
#include "libpressio_ext/cpp/data.h"
#include "libpressio_ext/cpp/metrics.h"
#include "libpressio_ext/cpp/options.h"
#include "libpressio_ext/cpp/pressio.h"
#include "std_compat/memory.h"

namespace diff_pdf {
static const uint64_t zero = 0;
struct metrics {
pressio_data histogram = pressio_data::copy(pressio_uint64_dtype, &zero, {1});
double interval = 0;
double min_diff = 0;
double max_diff = 0;
};
struct compute_metrics{
template <class ForwardIt1, class ForwardIt2>
metrics operator()(ForwardIt1 input_begin, ForwardIt1 input_end, ForwardIt2 input2_begin, ForwardIt2 input2_end) const
{
metrics m;
size_t num_elements = std::min(input_end-input_begin, input2_end-input2_begin);
if (num_elements == 0) {
return m;
}

m.max_diff = input_begin[0] - input2_begin[0];
m.min_diff = m.max_diff;
for (size_t i = 1; i < num_elements; ++i) {
double diff = input_begin[i] - input2_begin[i];
m.max_diff = std::max(m.max_diff, diff);
m.min_diff = std::min(m.min_diff, diff);
}
m.interval = (m.max_diff - m.min_diff)/pdf_intervals;
if (m.interval == 0) {
return m;
}


m.histogram = pressio_data::owning(pressio_uint64_dtype, {static_cast<size_t>(pdf_intervals)});
const auto dist_ptr = static_cast<uint64_t*>(m.histogram.data());
memset(dist_ptr, 0, m.histogram.size_in_bytes());

for (size_t i = 0; i < num_elements; ++i) {
auto diff = input_begin[i] - input2_begin[i];
auto idx = std::min(static_cast<size_t>((diff-m.min_diff)/m.interval), static_cast<size_t>(pdf_intervals - 1));
dist_ptr[idx]++;
}

return m;

}

uint64_t pdf_intervals;
};
}

class diff_pdf_plugin : public libpressio_metrics_plugin {

public:
void begin_compress(const struct pressio_data * input, struct pressio_data const * ) override {
input_data = pressio_data::clone(*input);
}
void end_decompress(struct pressio_data const*, struct pressio_data const* output, int ) override {
err_metrics = pressio_data_for_each<diff_pdf::metrics>(input_data, *output, diff_pdf::compute_metrics{pdf_intervals});
}

int set_options(pressio_options const& opts) override {
get(opts, "diff_pdf:intervals", &pdf_intervals);
return 0;
}
pressio_options get_options() const override {
pressio_options opts;
set(opts, "diff_pdf:intervals", pdf_intervals);
return opts;
}

struct pressio_options get_metrics_results() const override {
pressio_options opt;
if(err_metrics) {
set(opt, "diff_pdf:histogram", err_metrics->histogram);
set(opt, "diff_pdf:interval", err_metrics->interval);
set(opt, "diff_pdf:min_diff", err_metrics->min_diff);
set(opt, "diff_pdf:max_diff", err_metrics->max_diff);
} else {
set_type(opt, "diff_pdf:pdf", pressio_option_data_type);
}
return opt;
}
std::unique_ptr<libpressio_metrics_plugin> clone() override {
return compat::make_unique<diff_pdf_plugin>(*this);
}

const char* prefix() const override {
return "diff_pdf";
}


private:
uint64_t pdf_intervals = 2000;
pressio_data input_data = pressio_data::empty(pressio_byte_dtype, {});
compat::optional<diff_pdf::metrics> err_metrics;
};

static pressio_register metrics_diff_pdf_plugin(metrics_plugins(), "diff_pdf", [](){ return compat::make_unique<diff_pdf_plugin>(); });
2 changes: 1 addition & 1 deletion src/plugins/metrics/external.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class external_metric_plugin : public libpressio_metrics_plugin {
auto eq_pos = version_line.find('=') + 1;
if(version_line.substr(0, eq_pos) != "external:api=") {
//report error
return 0;
throw std::runtime_error("invalid format version");
}
return version_line.substr(eq_pos);
}
Expand Down
1 change: 1 addition & 0 deletions src/pressio_options_json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ void to_json(nlohmann::json& j, pressio_option const& option){
j["type"] = uint32_t{option.type()};
if(not option.has_value()) {
j["value"] = nullptr;
return;
}
switch(option.type()) {
case pressio_option_data_type:
Expand Down

0 comments on commit 17514fd

Please sign in to comment.