From e830629321f8ff197d0e4342d0d5531fd184b9c9 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Mon, 5 Jan 2026 13:28:07 -0500 Subject: [PATCH 01/12] Add QOI metric plugin --- CMakeLists.txt | 3 + src/plugins/metrics/qoi.cc | 162 +++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 src/plugins/metrics/qoi.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 936c206c..bc9d64d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,7 @@ libpressio_plugin_file(io/by_extension.cc) libpressio_plugin_file(io/posix.cc) libpressio_plugin_file(domains/malloc.cc) libpressio_plugin_file(domains/nonowning.cc) +libpressio_plugin_file(metrics/qoi.cc) #optional components created with libpressio_optional_component don't require dependencies #they can be enabled in two (non-exclusive) ways: @@ -180,6 +181,7 @@ libpressio_optional_component(numpy "build the numpy io plugin" /io/numpy.cc) libpressio_optional_component(copy_template "build the numpy io plugin" /io/copy_template.cc) libpressio_optional_component(size "build the size metrics plugin" /metrics/size.cc) libpressio_optional_component(time "build the time metrics plugin" /metrics/time.cc) +libpressio_optional_component(time "build the qoi metrics plugin" /metrics/qoi.cc) libpressio_optional_component(autocorr "build the autocorr metrics plugin" /metrics/autocorr.cc) libpressio_optional_component(chunking "build the chunking compressor plugin" "/compressors/chunking.cc;/compressors/chunking_impl.cc") libpressio_optional_component(delta_encoding "build the delta_encoding compressor plugin" /compressors/delta_encoding.cc) @@ -215,6 +217,7 @@ set(roibin_sources /compressors/roibin.cc /compressors/binning.cc /compressors/m libpressio_optional_component(roibin "build the roibin metacompressor" "${roibin_sources}") libpressio_optional_component(pipeline "build the pipeline metacompressor" /compressors/pipeline.cc) + option(LIBPRESSIO_INTERPROCEDURAL_OPTIMIZATION "Use interprocedural optimization (LTO)" OFF) if(LIBPRESSIO_INTERPROCEDURAL_OPTIMIZATION) cmake_policy(CMP0069 NEW) diff --git a/src/plugins/metrics/qoi.cc b/src/plugins/metrics/qoi.cc new file mode 100644 index 00000000..c09808d6 --- /dev/null +++ b/src/plugins/metrics/qoi.cc @@ -0,0 +1,162 @@ +// #include "pressio_options.h" +// #include "libpressio_ext/cpp/metrics.h" +// #include "libpressio_ext/cpp/pressio.h" +// #include "std_compat/memory.h" +#include "pressio_options.h" +#include "libpressio_ext/cpp/metrics.h" +#include "libpressio_ext/cpp/options.h" +#include "libpressio_ext/cpp/pressio.h" +#include "std_compat/memory.h" + + +// #include +#include +#include +#include +#include + + + + +namespace libpressio { namespace metrics { + +namespace qoi_ns { + +class qoi_plugin : public libpressio_metrics_plugin { + public: + int set_options(pressio_options const& options) override { + get_meta(options, "qoi:metric", metrics_plugins(), child_id, child); + // options.get("qoi:metric_name", &metric_name); + return 0; + } + pressio_options get_options() const override { + pressio_options opts; + set_meta(opts, "qoi:metric", child_id, child); + // opts.set("qoi:metric_name", metric_name); + return opts; + } + + int begin_check_options_impl(struct pressio_options const* opts) override { + return child->begin_check_options(opts); + } + + int end_check_options_impl(struct pressio_options const* opts, int rc) override { + return child->end_check_options(opts, rc); + } + + int begin_get_options_impl() override { + return child->begin_get_options(); + } + + int end_get_options_impl(struct pressio_options const* opts) override { + return child->end_get_options(opts); + } + + int begin_get_configuration_impl() override { + return child->begin_get_configuration(); + } + + int end_get_configuration_impl(struct pressio_options const& opts) override { + return child->end_get_configuration(opts); + } + + int begin_set_options_impl(struct pressio_options const& opts) override { + return child->begin_set_options(opts); + } + + int end_set_options_impl(struct pressio_options const& opts, int rc) override { + return child->end_set_options(opts, rc); + } + + int begin_compress_impl(const struct pressio_data * input, struct pressio_data const * output) override { + return child->begin_compress(input, output); + } + + int end_compress_impl(struct pressio_data const* input, pressio_data const * output, int rc) override { + // Logic to calculate min_v, max_v, p99_v, p999_v, wasserstein_v would go here + return child->end_compress(input, output, rc); + } + + int begin_decompress_impl(struct pressio_data const* input, pressio_data const* output) override { + return child->begin_decompress(input, output); + } + + int end_decompress_impl(struct pressio_data const* input, pressio_data const* output, int rc) override { + return child->end_decompress(input, output, rc); + } + + int begin_compress_many_impl(compat::span const& inputs, + compat::span const& outputs) override { + return child->begin_compress_many(inputs, outputs); + } + + int end_compress_many_impl(compat::span const& inputs, + compat::span const& outputs, int rc) override { + return child->end_compress_many(inputs, outputs, rc); + } + + int begin_decompress_many_impl(compat::span const& inputs, + compat::span const& outputs) override { + return child->begin_decompress_many(inputs, outputs); + } + + int end_decompress_many_impl(compat::span const& inputs, + compat::span const& outputs, int rc) override { + return child->end_decompress_many(inputs, outputs, rc); + } + + struct pressio_options get_configuration_impl() const override { + pressio_options opts; + set_meta_configuration(opts, "qoi:metric", metrics_plugins(), child); + set(opts, "pressio:stability", "stable"); + set(opts, "pressio:thread_safe", pressio_thread_safety_multiple); + set(opts, "predictors:requires_decompress", std::vector{"time:decompress", "time:decompress_many", "time:begin_decompress", "time:end_decompress", "time:begin_decompress_many", "time:end_decompress_many"}); + set(opts, "predictors:invalidate", std::vector{"predictors:runtime", "predictors:nondeterministc"}); + return opts; + } + + struct pressio_options get_documentation_impl() const override { + pressio_options opt; + set(opt, "pressio:description", R"()"); + return opt; + + } + + pressio_options get_metrics_results(pressio_options const & parent) override { + + pressio_options opt; + opt.copy_from(child->get_metrics_results(opt)); + pressio_data qoi_data; + + // if(get(opt, qoi, &qoi_data) == pressio_options_key_set) { + // printf("success------------------------------------"); + + // } + + + + return opt; + + } + + std::unique_ptr clone() override { + return compat::make_unique(*this); + } + + const char* prefix() const override { + return "qoi"; + } + + + + private: + + std::string qoi = "external:results:data"; + pressio_metrics child = metrics_plugins().build("noop"); + std::string child_id = "noop"; + // double mean = 0.0; +}; + +pressio_register registration(metrics_plugins(), "qoi", [](){ std::cout << "Registering qoi plugin\n"; return compat::make_unique(); }); + +}}} From a6435243335a740053ff346d0f1456ddcdb48d4f Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Mon, 5 Jan 2026 15:55:04 -0500 Subject: [PATCH 02/12] msg --- build/pressio_manual_register.cc | 89 ++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 build/pressio_manual_register.cc diff --git a/build/pressio_manual_register.cc b/build/pressio_manual_register.cc new file mode 100644 index 00000000..71c387c0 --- /dev/null +++ b/build/pressio_manual_register.cc @@ -0,0 +1,89 @@ + + #include + #include "libpressio_ext/cpp/registry.h" + + + namespace libpressio { + namespace compressors { + namespace noop_ns { + extern pressio_register registration; + } + namespace pressio_ns { + extern pressio_register registration; + } + } /* namespace compressors*/ + namespace domains { + namespace malloc_ns { + extern pressio_register registration; + } + namespace nonowning_ns { + extern pressio_register registration; + } + } /* namespace domains*/ + namespace domains_metrics { + namespace print_ns { + extern pressio_register registration; + } + } /* namespace domains_metrics*/ + namespace io { + namespace by_extension_ns { + extern pressio_register registration; + } + namespace noop_ns { + extern pressio_register registration; + } + namespace posix_ns { + extern pressio_register registration; + } + } /* namespace io*/ + namespace launch { + namespace external_forkexec_ns { + extern pressio_register registration; + } + } /* namespace launch*/ + namespace launch_metrics { + namespace noop_ns { + extern pressio_register registration; + } + namespace print_ns { + extern pressio_register registration; + } + } /* namespace launch_metrics*/ + namespace metrics { + namespace composite_ns { + extern pressio_register registration; + } + namespace error_stat_ns { + extern pressio_register registration; + } + namespace external_ns { + extern pressio_register registration; + } + namespace noop_ns { + extern pressio_register registration; + } + namespace qoi_ns { + extern pressio_register registration; + } + } /*namespace metrics*/ +} /*namespace libpressio*/ +extern "C" void pressio_register_all() { +libpressio::compressors::noop_ns::registration.ensure_registered(); +libpressio::compressors::pressio_ns::registration.ensure_registered(); +libpressio::domains::malloc_ns::registration.ensure_registered(); +libpressio::domains::nonowning_ns::registration.ensure_registered(); +libpressio::domains_metrics::print_ns::registration.ensure_registered(); +libpressio::io::by_extension_ns::registration.ensure_registered(); +libpressio::io::noop_ns::registration.ensure_registered(); +libpressio::io::posix_ns::registration.ensure_registered(); +libpressio::launch::external_forkexec_ns::registration.ensure_registered(); +libpressio::launch_metrics::noop_ns::registration.ensure_registered(); +libpressio::launch_metrics::print_ns::registration.ensure_registered(); +libpressio::metrics::composite_ns::registration.ensure_registered(); +libpressio::metrics::error_stat_ns::registration.ensure_registered(); +libpressio::metrics::external_ns::registration.ensure_registered(); +libpressio::metrics::noop_ns::registration.ensure_registered(); +libpressio::metrics::qoi_ns::registration.ensure_registered(); + + } + From 61fc6735644a272965adc3841806b39cd3b9d74f Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Sun, 11 Jan 2026 08:37:15 -0500 Subject: [PATCH 03/12] msg --- src/plugins/metrics/qoi.cc | 49 ++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/plugins/metrics/qoi.cc b/src/plugins/metrics/qoi.cc index c09808d6..850031fc 100644 --- a/src/plugins/metrics/qoi.cc +++ b/src/plugins/metrics/qoi.cc @@ -122,23 +122,52 @@ class qoi_plugin : public libpressio_metrics_plugin { } - pressio_options get_metrics_results(pressio_options const & parent) override { + // pressio_options get_metrics_results(pressio_options const & parent) override { - pressio_options opt; - opt.copy_from(child->get_metrics_results(opt)); - pressio_data qoi_data; + // pressio_options opt; + // opt.copy_from(child->get_metrics_results(opt)); + // pressio_data qoi_data; - // if(get(opt, qoi, &qoi_data) == pressio_options_key_set) { - // printf("success------------------------------------"); + // // if(get(opt, qoi, &qoi_data) == pressio_options_key_set) { + // // printf("success------------------------------------"); - // } + // // } - return opt; - + // return opt; + + // } + pressio_options get_metrics_results(pressio_options const & parent) override { + pressio_options opt = child->get_metrics_results(parent); + pressio_data qoi_data; + + if(get(opt, "external:results:data", &qoi_data) == pressio_options_key_set) { + // std::string json_str(static_cast(qoi_data.data()), qoi_data.size()); + printf("success-----------------------"); + // try { + // nlohmann::json meta = nlohmann::json::parse(json_str); + + // if(meta.contains("mean")) { + // double mean = meta["mean"].get(); + + // // 将 mean 存入新的 pressio_data(float64 类型) + // pressio_data mean_data = pressio_data::owning(pressio_double_dtype, {1}); + // static_cast(mean_data.data())[0] = mean; + + // // 放入当前 metrics 的输出 + // set(opt, "qoi:results:data", mean_data); + // } + + // } catch(const std::exception& e) { + // std::cerr << "[QOI] Failed to parse JSON: " << e.what() << std::endl; + // } } + return opt; +} + + std::unique_ptr clone() override { return compat::make_unique(*this); } @@ -159,4 +188,4 @@ class qoi_plugin : public libpressio_metrics_plugin { pressio_register registration(metrics_plugins(), "qoi", [](){ std::cout << "Registering qoi plugin\n"; return compat::make_unique(); }); -}}} +}}} \ No newline at end of file From f7c100ad07382e6752be0f8b9f631559c87d4bb1 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Sun, 11 Jan 2026 09:00:29 -0500 Subject: [PATCH 04/12] msg --- build/pressio_manual_register.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/pressio_manual_register.cc b/build/pressio_manual_register.cc index 71c387c0..9d0b90f3 100644 --- a/build/pressio_manual_register.cc +++ b/build/pressio_manual_register.cc @@ -62,9 +62,6 @@ namespace noop_ns { extern pressio_register registration; } - namespace qoi_ns { - extern pressio_register registration; - } } /*namespace metrics*/ } /*namespace libpressio*/ extern "C" void pressio_register_all() { @@ -83,7 +80,6 @@ libpressio::metrics::composite_ns::registration.ensure_registered(); libpressio::metrics::error_stat_ns::registration.ensure_registered(); libpressio::metrics::external_ns::registration.ensure_registered(); libpressio::metrics::noop_ns::registration.ensure_registered(); -libpressio::metrics::qoi_ns::registration.ensure_registered(); } From 7886ed5475574b9f9364a69d975538b8c9a0b602 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Mon, 12 Jan 2026 09:34:51 -0500 Subject: [PATCH 05/12] cp4-5 --- src/plugins/metrics/composite.cc | 2 +- src/plugins/metrics/external.cc | 11 ++-- src/plugins/metrics/qoi.cc | 93 ++++++++++++++++++-------------- 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/src/plugins/metrics/composite.cc b/src/plugins/metrics/composite.cc index 7104e53b..f0edbc8e 100644 --- a/src/plugins/metrics/composite.cc +++ b/src/plugins/metrics/composite.cc @@ -157,7 +157,7 @@ class composite_plugin : public libpressio_metrics_plugin { pressio_options get_metrics_results(pressio_options const &) override { struct pressio_options metrics_result; for (auto const& plugin : plugins) { - pressio_options plugin_options = plugin->get_metrics_results({}); + pressio_options plugin_options = plugin->get_metrics_results(metrics_result); auto tmp = pressio_options_merge(&metrics_result, &plugin_options); metrics_result = std::move(*tmp); pressio_options_free(tmp); diff --git a/src/plugins/metrics/external.cc b/src/plugins/metrics/external.cc index db4009c2..4b7968d3 100644 --- a/src/plugins/metrics/external.cc +++ b/src/plugins/metrics/external.cc @@ -86,15 +86,10 @@ class external_metric_plugin : public libpressio_metrics_plugin { return 0; } - int end_decompress_many_impl(compat::span const& , + int end_decompress_many_impl(compat::span const& inputs, compat::span const& outputs, int ) override { - if(use_many or outputs.size() > 1) { - std::vector input_ptrs(input_data.size()); - for (size_t i = 0; i < input_data.size(); ++i) { - input_ptrs[i] = &input_data[i]; - } - compat::span input_datasets{input_ptrs.data(), input_ptrs.size()}; - run_external(input_datasets, outputs); + if(use_many or outputs.size() > 1 or ((not use_many) and outputs.size() == 1 and field_names.size() == 1)) { + run_external(inputs, outputs); } return 0; } diff --git a/src/plugins/metrics/qoi.cc b/src/plugins/metrics/qoi.cc index 850031fc..b3b663bc 100644 --- a/src/plugins/metrics/qoi.cc +++ b/src/plugins/metrics/qoi.cc @@ -11,9 +11,12 @@ // #include #include +#include #include #include #include +#include +#include @@ -25,6 +28,8 @@ namespace qoi_ns { class qoi_plugin : public libpressio_metrics_plugin { public: int set_options(pressio_options const& options) override { + fprintf(stderr, "[QOI] set_options called\n"); + fflush(stderr); get_meta(options, "qoi:metric", metrics_plugins(), child_id, child); // options.get("qoi:metric_name", &metric_name); return 0; @@ -74,6 +79,7 @@ class qoi_plugin : public libpressio_metrics_plugin { int end_compress_impl(struct pressio_data const* input, pressio_data const * output, int rc) override { // Logic to calculate min_v, max_v, p99_v, p999_v, wasserstein_v would go here + printf("--------------"); return child->end_compress(input, output, rc); } @@ -122,51 +128,56 @@ class qoi_plugin : public libpressio_metrics_plugin { } - // pressio_options get_metrics_results(pressio_options const & parent) override { - - // pressio_options opt; - // opt.copy_from(child->get_metrics_results(opt)); - // pressio_data qoi_data; - - // // if(get(opt, qoi, &qoi_data) == pressio_options_key_set) { - // // printf("success------------------------------------"); - - // // } - - - - // return opt; - - // } pressio_options get_metrics_results(pressio_options const & parent) override { - pressio_options opt = child->get_metrics_results(parent); - pressio_data qoi_data; + pressio_options opt = child->get_metrics_results(parent); + pressio_data qoi_data; + double qoi_value; + + // Step 5: Get pressio_data from parent (when used with composite, parent contains accumulated results) + // First try to get as pressio_data + if(get(parent, qoi, &qoi_data) == pressio_options_key_set) { + fprintf(stderr, "[QOI] Got pressio_data from parent, key=%s\n", qoi.c_str()); + // Step 5: Access values inside pressio_data + // Use templated accessors to safely iterate over the data + auto* ptr = static_cast(qoi_data.data()); + size_t n = qoi_data.num_elements(); + fprintf(stderr, "[QOI] pressio_data: n=%zu, dtype=%d\n", n, qoi_data.dtype()); + + // Calculate mean from pressio_data + if (n > 0 && qoi_data.dtype() == pressio_double_dtype) { + double mean = std::accumulate(ptr, ptr + n, 0.0) / static_cast(n); + fprintf(stderr, "[QOI] Calculated mean=%f from pressio_data\n", mean); + set(opt, "qoi:mean", mean); + + // Verify it was set + double verify_mean; + if(get(opt, "qoi:mean", &verify_mean) == pressio_options_key_set) { + fprintf(stderr, "[QOI] Verified qoi:mean=%f is set in opt\n", verify_mean); + } else { + fprintf(stderr, "[QOI] ERROR: qoi:mean was NOT set in opt!\n"); + } + } + } + // Fallback: if pressio_data not found, try to get as double + else if(get(parent, qoi, &qoi_value) == pressio_options_key_set) { + fprintf(stderr, "[QOI] Got double from parent, key=%s, value=%f\n", qoi.c_str(), qoi_value); + // For single double value, mean is the value itself + set(opt, "qoi:mean", qoi_value); + + // Verify it was set + double verify_mean; + if(get(opt, "qoi:mean", &verify_mean) == pressio_options_key_set) { + fprintf(stderr, "[QOI] Verified qoi:mean=%f is set in opt\n", verify_mean); + } else { + fprintf(stderr, "[QOI] ERROR: qoi:mean was NOT set in opt!\n"); + } + } else { + fprintf(stderr, "[QOI] WARNING: Could not get %s from parent\n", qoi.c_str()); + } - if(get(opt, "external:results:data", &qoi_data) == pressio_options_key_set) { - // std::string json_str(static_cast(qoi_data.data()), qoi_data.size()); - printf("success-----------------------"); - // try { - // nlohmann::json meta = nlohmann::json::parse(json_str); - - // if(meta.contains("mean")) { - // double mean = meta["mean"].get(); - - // // 将 mean 存入新的 pressio_data(float64 类型) - // pressio_data mean_data = pressio_data::owning(pressio_double_dtype, {1}); - // static_cast(mean_data.data())[0] = mean; - - // // 放入当前 metrics 的输出 - // set(opt, "qoi:results:data", mean_data); - // } - - // } catch(const std::exception& e) { - // std::cerr << "[QOI] Failed to parse JSON: " << e.what() << std::endl; - // } + return opt; } - return opt; -} - std::unique_ptr clone() override { return compat::make_unique(*this); From 71e80587bc9b6f38b618202cb242f1eaeeeb7a95 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Mon, 12 Jan 2026 18:16:36 -0500 Subject: [PATCH 06/12] Revert composite.cc and external.cc to 1.0.5 state --- src/plugins/metrics/composite.cc | 17 ++--------------- src/plugins/metrics/external.cc | 11 ++++++++--- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/plugins/metrics/composite.cc b/src/plugins/metrics/composite.cc index f0edbc8e..c32e1796 100644 --- a/src/plugins/metrics/composite.cc +++ b/src/plugins/metrics/composite.cc @@ -157,7 +157,7 @@ class composite_plugin : public libpressio_metrics_plugin { pressio_options get_metrics_results(pressio_options const &) override { struct pressio_options metrics_result; for (auto const& plugin : plugins) { - pressio_options plugin_options = plugin->get_metrics_results(metrics_result); + pressio_options plugin_options = plugin->get_metrics_results({}); auto tmp = pressio_options_merge(&metrics_result, &plugin_options); metrics_result = std::move(*tmp); pressio_options_free(tmp); @@ -217,20 +217,7 @@ class composite_plugin : public libpressio_metrics_plugin { set(options, "composite:decompression_rate", "decompression rate for the compress method, activated by size and time (kB/s)"); set(options, "composite:decompression_rate_many", "decompression rate for the compress_many method, activated by size and time (kB/s)"); set(options, "composite:names", "the names to use for the constructed metrics plugins"); - set(options, "composite:scripts", R"(a vector of lua scripts used to compute metrics from other metrics that have been previously computed - - inputs: - - + table called `metrics` with the metrics computed by a child of the composite metric. - + any of the functions from lua's [base and math](https://www.lua.org/manual/5.4/manual.html#6) libraries can be used. - - outputs: - - + the script is expected to return a pair of string, optional (i.e. nil in lua), the output is translated - to a result variable with a name like `composite:$name`. For example, `return "objective", 1.2` would create a - variable `composite:objective` with a value of `1.2`. - - )"); + set(options, "composite:scripts", "a lua script used to compute metrics from other metrics that have been previously computed"); set(options, "pressio:description", "meta-metric that runs a set of metrics in sequence"); return options; diff --git a/src/plugins/metrics/external.cc b/src/plugins/metrics/external.cc index 4b7968d3..db4009c2 100644 --- a/src/plugins/metrics/external.cc +++ b/src/plugins/metrics/external.cc @@ -86,10 +86,15 @@ class external_metric_plugin : public libpressio_metrics_plugin { return 0; } - int end_decompress_many_impl(compat::span const& inputs, + int end_decompress_many_impl(compat::span const& , compat::span const& outputs, int ) override { - if(use_many or outputs.size() > 1 or ((not use_many) and outputs.size() == 1 and field_names.size() == 1)) { - run_external(inputs, outputs); + if(use_many or outputs.size() > 1) { + std::vector input_ptrs(input_data.size()); + for (size_t i = 0; i < input_data.size(); ++i) { + input_ptrs[i] = &input_data[i]; + } + compat::span input_datasets{input_ptrs.data(), input_ptrs.size()}; + run_external(input_datasets, outputs); } return 0; } From 77bc029f31c33b9ee3ace4fb22794db9b0c046d8 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Mon, 12 Jan 2026 18:18:33 -0500 Subject: [PATCH 07/12] Revert composite and external metrics to 1.0.5 behavior --- src/plugins/metrics/composite.cc | 17 +++++++++++++++-- src/plugins/metrics/external.cc | 11 +++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/plugins/metrics/composite.cc b/src/plugins/metrics/composite.cc index c32e1796..f0edbc8e 100644 --- a/src/plugins/metrics/composite.cc +++ b/src/plugins/metrics/composite.cc @@ -157,7 +157,7 @@ class composite_plugin : public libpressio_metrics_plugin { pressio_options get_metrics_results(pressio_options const &) override { struct pressio_options metrics_result; for (auto const& plugin : plugins) { - pressio_options plugin_options = plugin->get_metrics_results({}); + pressio_options plugin_options = plugin->get_metrics_results(metrics_result); auto tmp = pressio_options_merge(&metrics_result, &plugin_options); metrics_result = std::move(*tmp); pressio_options_free(tmp); @@ -217,7 +217,20 @@ class composite_plugin : public libpressio_metrics_plugin { set(options, "composite:decompression_rate", "decompression rate for the compress method, activated by size and time (kB/s)"); set(options, "composite:decompression_rate_many", "decompression rate for the compress_many method, activated by size and time (kB/s)"); set(options, "composite:names", "the names to use for the constructed metrics plugins"); - set(options, "composite:scripts", "a lua script used to compute metrics from other metrics that have been previously computed"); + set(options, "composite:scripts", R"(a vector of lua scripts used to compute metrics from other metrics that have been previously computed + + inputs: + + + table called `metrics` with the metrics computed by a child of the composite metric. + + any of the functions from lua's [base and math](https://www.lua.org/manual/5.4/manual.html#6) libraries can be used. + + outputs: + + + the script is expected to return a pair of string, optional (i.e. nil in lua), the output is translated + to a result variable with a name like `composite:$name`. For example, `return "objective", 1.2` would create a + variable `composite:objective` with a value of `1.2`. + + )"); set(options, "pressio:description", "meta-metric that runs a set of metrics in sequence"); return options; diff --git a/src/plugins/metrics/external.cc b/src/plugins/metrics/external.cc index db4009c2..4b7968d3 100644 --- a/src/plugins/metrics/external.cc +++ b/src/plugins/metrics/external.cc @@ -86,15 +86,10 @@ class external_metric_plugin : public libpressio_metrics_plugin { return 0; } - int end_decompress_many_impl(compat::span const& , + int end_decompress_many_impl(compat::span const& inputs, compat::span const& outputs, int ) override { - if(use_many or outputs.size() > 1) { - std::vector input_ptrs(input_data.size()); - for (size_t i = 0; i < input_data.size(); ++i) { - input_ptrs[i] = &input_data[i]; - } - compat::span input_datasets{input_ptrs.data(), input_ptrs.size()}; - run_external(input_datasets, outputs); + if(use_many or outputs.size() > 1 or ((not use_many) and outputs.size() == 1 and field_names.size() == 1)) { + run_external(inputs, outputs); } return 0; } From 01a9f335489b5cca278d58be0c3e16a88801e4f2 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Mon, 12 Jan 2026 18:42:20 -0500 Subject: [PATCH 08/12] Revert composite.cc and external.cc to pre-cp4-5 state --- src/plugins/metrics/composite.cc | 2 +- src/plugins/metrics/external.cc | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/plugins/metrics/composite.cc b/src/plugins/metrics/composite.cc index f0edbc8e..7104e53b 100644 --- a/src/plugins/metrics/composite.cc +++ b/src/plugins/metrics/composite.cc @@ -157,7 +157,7 @@ class composite_plugin : public libpressio_metrics_plugin { pressio_options get_metrics_results(pressio_options const &) override { struct pressio_options metrics_result; for (auto const& plugin : plugins) { - pressio_options plugin_options = plugin->get_metrics_results(metrics_result); + pressio_options plugin_options = plugin->get_metrics_results({}); auto tmp = pressio_options_merge(&metrics_result, &plugin_options); metrics_result = std::move(*tmp); pressio_options_free(tmp); diff --git a/src/plugins/metrics/external.cc b/src/plugins/metrics/external.cc index 4b7968d3..db4009c2 100644 --- a/src/plugins/metrics/external.cc +++ b/src/plugins/metrics/external.cc @@ -86,10 +86,15 @@ class external_metric_plugin : public libpressio_metrics_plugin { return 0; } - int end_decompress_many_impl(compat::span const& inputs, + int end_decompress_many_impl(compat::span const& , compat::span const& outputs, int ) override { - if(use_many or outputs.size() > 1 or ((not use_many) and outputs.size() == 1 and field_names.size() == 1)) { - run_external(inputs, outputs); + if(use_many or outputs.size() > 1) { + std::vector input_ptrs(input_data.size()); + for (size_t i = 0; i < input_data.size(); ++i) { + input_ptrs[i] = &input_data[i]; + } + compat::span input_datasets{input_ptrs.data(), input_ptrs.size()}; + run_external(input_datasets, outputs); } return 0; } From 31f872d33f4f6354a9fdd87f2381af40f03101ba Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Fri, 16 Jan 2026 21:08:03 -0500 Subject: [PATCH 09/12] extract external results and convert to pressio data --- CMakeLists.txt | 4 +- src/plugins/metrics/qoi.cc | 94 ++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc9d64d6..a613e41e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,7 +151,7 @@ libpressio_plugin_file(io/by_extension.cc) libpressio_plugin_file(io/posix.cc) libpressio_plugin_file(domains/malloc.cc) libpressio_plugin_file(domains/nonowning.cc) -libpressio_plugin_file(metrics/qoi.cc) +# libpressio_plugin_file(metrics/qoi.cc) #optional components created with libpressio_optional_component don't require dependencies #they can be enabled in two (non-exclusive) ways: @@ -181,7 +181,7 @@ libpressio_optional_component(numpy "build the numpy io plugin" /io/numpy.cc) libpressio_optional_component(copy_template "build the numpy io plugin" /io/copy_template.cc) libpressio_optional_component(size "build the size metrics plugin" /metrics/size.cc) libpressio_optional_component(time "build the time metrics plugin" /metrics/time.cc) -libpressio_optional_component(time "build the qoi metrics plugin" /metrics/qoi.cc) +libpressio_optional_component(qoi "build the qoi metrics plugin" /metrics/qoi.cc) libpressio_optional_component(autocorr "build the autocorr metrics plugin" /metrics/autocorr.cc) libpressio_optional_component(chunking "build the chunking compressor plugin" "/compressors/chunking.cc;/compressors/chunking_impl.cc") libpressio_optional_component(delta_encoding "build the delta_encoding compressor plugin" /compressors/delta_encoding.cc) diff --git a/src/plugins/metrics/qoi.cc b/src/plugins/metrics/qoi.cc index b3b663bc..06f31a71 100644 --- a/src/plugins/metrics/qoi.cc +++ b/src/plugins/metrics/qoi.cc @@ -6,6 +6,7 @@ #include "libpressio_ext/cpp/metrics.h" #include "libpressio_ext/cpp/options.h" #include "libpressio_ext/cpp/pressio.h" +#include "libpressio_ext/cpp/data.h" #include "std_compat/memory.h" @@ -132,47 +133,70 @@ class qoi_plugin : public libpressio_metrics_plugin { pressio_options opt = child->get_metrics_results(parent); pressio_data qoi_data; double qoi_value; - - // Step 5: Get pressio_data from parent (when used with composite, parent contains accumulated results) - // First try to get as pressio_data - if(get(parent, qoi, &qoi_data) == pressio_options_key_set) { - fprintf(stderr, "[QOI] Got pressio_data from parent, key=%s\n", qoi.c_str()); - // Step 5: Access values inside pressio_data - // Use templated accessors to safely iterate over the data - auto* ptr = static_cast(qoi_data.data()); - size_t n = qoi_data.num_elements(); - fprintf(stderr, "[QOI] pressio_data: n=%zu, dtype=%d\n", n, qoi_data.dtype()); + // Iterate over all keys in child's results to find JSON-parsed keys + // JSON format: {"mean": 158.7, "std": 2.5} -> "external:results:mean", "external:results:std" + // Key-value format: "data=158.7\ndata=159.2..." -> "external:results:data" (pressio_data array) + const std::string prefix = "external:results:"; + std::vector values; // Collect all values from JSON keys + bool found_any_json_key = false; + // Step 1: Iterate through all keys in child's results to find JSON keys + fprintf(stderr, "[QOI] DEBUG: Searching for JSON keys with prefix '%s':\n", prefix.c_str()); + for (auto const& item : opt) { + const std::string& key = item.first; - // Calculate mean from pressio_data - if (n > 0 && qoi_data.dtype() == pressio_double_dtype) { - double mean = std::accumulate(ptr, ptr + n, 0.0) / static_cast(n); - fprintf(stderr, "[QOI] Calculated mean=%f from pressio_data\n", mean); - set(opt, "qoi:mean", mean); + // Check if key starts with "external:results:" (JSON-parsed keys) + if (key.find(prefix) == 0) { + std::string json_key = key.substr(prefix.length()); // Extract JSON key (e.g., "mean") + fprintf(stderr, "[QOI] Found JSON key: '%s' -> full key: '%s'\n", json_key.c_str(), key.c_str()); + found_any_json_key = true; - // Verify it was set - double verify_mean; - if(get(opt, "qoi:mean", &verify_mean) == pressio_options_key_set) { - fprintf(stderr, "[QOI] Verified qoi:mean=%f is set in opt\n", verify_mean); - } else { - fprintf(stderr, "[QOI] ERROR: qoi:mean was NOT set in opt!\n"); + // Try to get as pressio_data (for arrays) + if (get(opt, key, &qoi_data) == pressio_options_key_set) { + fprintf(stderr, "[QOI] - Key '%s' is pressio_data array\n", json_key.c_str()); + auto* ptr = static_cast(qoi_data.data()); + size_t n = qoi_data.num_elements(); + + + } + // Try to get as double (for single values) + else if (get(opt, key, &qoi_value) == pressio_options_key_set) { + fprintf(stderr, "[QOI] - Key '%s' is double: %f\n", json_key.c_str(), qoi_value); + values.push_back(qoi_value); } } } - // Fallback: if pressio_data not found, try to get as double - else if(get(parent, qoi, &qoi_value) == pressio_options_key_set) { - fprintf(stderr, "[QOI] Got double from parent, key=%s, value=%f\n", qoi.c_str(), qoi_value); - // For single double value, mean is the value itself - set(opt, "qoi:mean", qoi_value); + + + // Step 3: Convert collected values to pressio_data and iterate with pointer + if (found_any_json_key && !values.empty()) { + // Create pressio_data from collected values using copy (which copies the data) + pressio_data qoi_result = pressio_data::copy(pressio_double_dtype, values.data(), {values.size()}); - // Verify it was set - double verify_mean; - if(get(opt, "qoi:mean", &verify_mean) == pressio_options_key_set) { - fprintf(stderr, "[QOI] Verified qoi:mean=%f is set in opt\n", verify_mean); - } else { - fprintf(stderr, "[QOI] ERROR: qoi:mean was NOT set in opt!\n"); - } + // Iterate through the data using pointer + const double* ptr = static_cast(qoi_result.data()); + size_t n = qoi_result.num_elements(); + + fprintf(stderr, "[QOI] Created pressio_data with %zu elements, iterating with pointer:\n", n); + // for (size_t i = 0; i < n; ++i) { + // fprintf(stderr, "[QOI] [%zu] = %f\n", i, ptr[i]); + + // Example: if this is the first value and it's "mean", set qoi:mean + // if (i == 0) { + // // Assuming first value is mean (can be customized based on your needs) + // set(opt, "qoi:mean", ptr[i]); + // fprintf(stderr, "[QOI] Set qoi:mean=%f from pressio_data pointer[0]\n", ptr[i]); + // } + // } + + // Store the entire pressio_data as qoi:data + set(opt, "qoi:data", qoi_result); } else { - fprintf(stderr, "[QOI] WARNING: Could not get %s from parent\n", qoi.c_str()); + // Step 4: If still not found, report warning + fprintf(stderr, "[QOI] WARNING: No JSON keys found with prefix '%s' in child results or parent\n", prefix.c_str()); + fprintf(stderr, "[QOI] Available keys in child results:\n"); + for (auto const& item : opt) { + fprintf(stderr, "[QOI] - %s\n", item.first.c_str()); + } } return opt; @@ -191,7 +215,7 @@ class qoi_plugin : public libpressio_metrics_plugin { private: - std::string qoi = "external:results:data"; + std::string qoi = "external:results"; // Base prefix for JSON results: {"mean": value} -> external:results:mean pressio_metrics child = metrics_plugins().build("noop"); std::string child_id = "noop"; // double mean = 0.0; From 9d123d3752281c809542b99a7197dab6542cffb4 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Fri, 16 Jan 2026 21:18:22 -0500 Subject: [PATCH 10/12] removed unncessary comments --- build/pressio_manual_register.cc | 85 -------------------------------- src/plugins/metrics/qoi.cc | 11 +---- 2 files changed, 1 insertion(+), 95 deletions(-) delete mode 100644 build/pressio_manual_register.cc diff --git a/build/pressio_manual_register.cc b/build/pressio_manual_register.cc deleted file mode 100644 index 9d0b90f3..00000000 --- a/build/pressio_manual_register.cc +++ /dev/null @@ -1,85 +0,0 @@ - - #include - #include "libpressio_ext/cpp/registry.h" - - - namespace libpressio { - namespace compressors { - namespace noop_ns { - extern pressio_register registration; - } - namespace pressio_ns { - extern pressio_register registration; - } - } /* namespace compressors*/ - namespace domains { - namespace malloc_ns { - extern pressio_register registration; - } - namespace nonowning_ns { - extern pressio_register registration; - } - } /* namespace domains*/ - namespace domains_metrics { - namespace print_ns { - extern pressio_register registration; - } - } /* namespace domains_metrics*/ - namespace io { - namespace by_extension_ns { - extern pressio_register registration; - } - namespace noop_ns { - extern pressio_register registration; - } - namespace posix_ns { - extern pressio_register registration; - } - } /* namespace io*/ - namespace launch { - namespace external_forkexec_ns { - extern pressio_register registration; - } - } /* namespace launch*/ - namespace launch_metrics { - namespace noop_ns { - extern pressio_register registration; - } - namespace print_ns { - extern pressio_register registration; - } - } /* namespace launch_metrics*/ - namespace metrics { - namespace composite_ns { - extern pressio_register registration; - } - namespace error_stat_ns { - extern pressio_register registration; - } - namespace external_ns { - extern pressio_register registration; - } - namespace noop_ns { - extern pressio_register registration; - } - } /*namespace metrics*/ -} /*namespace libpressio*/ -extern "C" void pressio_register_all() { -libpressio::compressors::noop_ns::registration.ensure_registered(); -libpressio::compressors::pressio_ns::registration.ensure_registered(); -libpressio::domains::malloc_ns::registration.ensure_registered(); -libpressio::domains::nonowning_ns::registration.ensure_registered(); -libpressio::domains_metrics::print_ns::registration.ensure_registered(); -libpressio::io::by_extension_ns::registration.ensure_registered(); -libpressio::io::noop_ns::registration.ensure_registered(); -libpressio::io::posix_ns::registration.ensure_registered(); -libpressio::launch::external_forkexec_ns::registration.ensure_registered(); -libpressio::launch_metrics::noop_ns::registration.ensure_registered(); -libpressio::launch_metrics::print_ns::registration.ensure_registered(); -libpressio::metrics::composite_ns::registration.ensure_registered(); -libpressio::metrics::error_stat_ns::registration.ensure_registered(); -libpressio::metrics::external_ns::registration.ensure_registered(); -libpressio::metrics::noop_ns::registration.ensure_registered(); - - } - diff --git a/src/plugins/metrics/qoi.cc b/src/plugins/metrics/qoi.cc index 06f31a71..75470821 100644 --- a/src/plugins/metrics/qoi.cc +++ b/src/plugins/metrics/qoi.cc @@ -177,16 +177,7 @@ class qoi_plugin : public libpressio_metrics_plugin { size_t n = qoi_result.num_elements(); fprintf(stderr, "[QOI] Created pressio_data with %zu elements, iterating with pointer:\n", n); - // for (size_t i = 0; i < n; ++i) { - // fprintf(stderr, "[QOI] [%zu] = %f\n", i, ptr[i]); - - // Example: if this is the first value and it's "mean", set qoi:mean - // if (i == 0) { - // // Assuming first value is mean (can be customized based on your needs) - // set(opt, "qoi:mean", ptr[i]); - // fprintf(stderr, "[QOI] Set qoi:mean=%f from pressio_data pointer[0]\n", ptr[i]); - // } - // } + // Store the entire pressio_data as qoi:data set(opt, "qoi:data", qoi_result); From bacbe5f5020dad74e6c29741e24319743b937687 Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Sat, 17 Jan 2026 01:02:40 -0500 Subject: [PATCH 11/12] step4 fininshed --- src/plugins/metrics/qoi.cc | 91 ++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/src/plugins/metrics/qoi.cc b/src/plugins/metrics/qoi.cc index 75470821..f8234f1c 100644 --- a/src/plugins/metrics/qoi.cc +++ b/src/plugins/metrics/qoi.cc @@ -22,6 +22,8 @@ + + namespace libpressio { namespace metrics { namespace qoi_ns { @@ -29,10 +31,7 @@ namespace qoi_ns { class qoi_plugin : public libpressio_metrics_plugin { public: int set_options(pressio_options const& options) override { - fprintf(stderr, "[QOI] set_options called\n"); - fflush(stderr); get_meta(options, "qoi:metric", metrics_plugins(), child_id, child); - // options.get("qoi:metric_name", &metric_name); return 0; } pressio_options get_options() const override { @@ -75,12 +74,14 @@ class qoi_plugin : public libpressio_metrics_plugin { } int begin_compress_impl(const struct pressio_data * input, struct pressio_data const * output) override { + // std::cout << "[QOI] begin_compress_impl: called" << std::endl; return child->begin_compress(input, output); } int end_compress_impl(struct pressio_data const* input, pressio_data const * output, int rc) override { // Logic to calculate min_v, max_v, p99_v, p999_v, wasserstein_v would go here - printf("--------------"); + + return child->end_compress(input, output, rc); } @@ -89,6 +90,7 @@ class qoi_plugin : public libpressio_metrics_plugin { } int end_decompress_impl(struct pressio_data const* input, pressio_data const* output, int rc) override { + return child->end_decompress(input, output, rc); } @@ -131,63 +133,43 @@ class qoi_plugin : public libpressio_metrics_plugin { pressio_options get_metrics_results(pressio_options const & parent) override { pressio_options opt = child->get_metrics_results(parent); - pressio_data qoi_data; - double qoi_value; - // Iterate over all keys in child's results to find JSON-parsed keys - // JSON format: {"mean": 158.7, "std": 2.5} -> "external:results:mean", "external:results:std" - // Key-value format: "data=158.7\ndata=159.2..." -> "external:results:data" (pressio_data array) - const std::string prefix = "external:results:"; - std::vector values; // Collect all values from JSON keys - bool found_any_json_key = false; - // Step 1: Iterate through all keys in child's results to find JSON keys - fprintf(stderr, "[QOI] DEBUG: Searching for JSON keys with prefix '%s':\n", prefix.c_str()); + + values.clear(); // Clear previous values + for (auto const& item : opt) { const std::string& key = item.first; + const pressio_option& option = item.second; - // Check if key starts with "external:results:" (JSON-parsed keys) - if (key.find(prefix) == 0) { - std::string json_key = key.substr(prefix.length()); // Extract JSON key (e.g., "mean") - fprintf(stderr, "[QOI] Found JSON key: '%s' -> full key: '%s'\n", json_key.c_str(), key.c_str()); - found_any_json_key = true; - - // Try to get as pressio_data (for arrays) - if (get(opt, key, &qoi_data) == pressio_options_key_set) { - fprintf(stderr, "[QOI] - Key '%s' is pressio_data array\n", json_key.c_str()); - auto* ptr = static_cast(qoi_data.data()); - size_t n = qoi_data.num_elements(); + // Check if key starts with qoi ("external:results:") + if (key.find(qoi) == 0) { + // Try to get as pressio_data (for arrays) - directly from item.second + if (option.holds_alternative() && option.has_value()) { + pressio_data temp_data = option.get_value(); + const double* ptr = static_cast(temp_data.data()); + size_t n = temp_data.num_elements(); - + // Put all values from pressio_data into values vector using pointer + if (ptr != nullptr && n > 0 && temp_data.dtype() == pressio_double_dtype) { + for (size_t i = 0; i < n; ++i) { + values.push_back(ptr[i]); + } + } } - // Try to get as double (for single values) - else if (get(opt, key, &qoi_value) == pressio_options_key_set) { - fprintf(stderr, "[QOI] - Key '%s' is double: %f\n", json_key.c_str(), qoi_value); - values.push_back(qoi_value); + // Try to get as double (for single values) - directly from item.second + else if (option.holds_alternative() && option.has_value()) { + double temp_value = option.get_value(); + values.push_back(temp_value); } } } + std::cout << "[QOI] Total values in vector: " << values.size() << std::endl; + for (size_t i = 0; i < values.size(); ++i) { + std::cout << "[QOI] values[" << i << "] = " << values[i] << std::endl; + } - - // Step 3: Convert collected values to pressio_data and iterate with pointer - if (found_any_json_key && !values.empty()) { - // Create pressio_data from collected values using copy (which copies the data) - pressio_data qoi_result = pressio_data::copy(pressio_double_dtype, values.data(), {values.size()}); - - // Iterate through the data using pointer - const double* ptr = static_cast(qoi_result.data()); - size_t n = qoi_result.num_elements(); - - fprintf(stderr, "[QOI] Created pressio_data with %zu elements, iterating with pointer:\n", n); - - - // Store the entire pressio_data as qoi:data - set(opt, "qoi:data", qoi_result); - } else { - // Step 4: If still not found, report warning - fprintf(stderr, "[QOI] WARNING: No JSON keys found with prefix '%s' in child results or parent\n", prefix.c_str()); - fprintf(stderr, "[QOI] Available keys in child results:\n"); - for (auto const& item : opt) { - fprintf(stderr, "[QOI] - %s\n", item.first.c_str()); - } + if (!values.empty()) { + qoi_data = pressio_data::copy(pressio_double_dtype, values.data(), {values.size()}); + set(opt, "qoi:data", qoi_data); } return opt; @@ -206,9 +188,12 @@ class qoi_plugin : public libpressio_metrics_plugin { private: - std::string qoi = "external:results"; // Base prefix for JSON results: {"mean": value} -> external:results:mean + std::string qoi = "external:results:"; // Base prefix for JSON results: {"mean": value} -> external:results:mean pressio_metrics child = metrics_plugins().build("noop"); std::string child_id = "noop"; + pressio_data qoi_data = pressio_data::empty(pressio_byte_dtype, {}); + std::vector values; + // Store qoi:data as member (like kth_error.cc) // double mean = 0.0; }; From 9d12a4361602f73e7ca5afb8f61fd175911da95f Mon Sep 17 00:00:00 2001 From: Ziwei Qiu Date: Fri, 23 Jan 2026 15:22:48 -0500 Subject: [PATCH 12/12] halo metrics finished --- CMakeLists.txt | 1 - src/plugins/metrics/qoi.cc | 190 ++++++++++++++++++++++++++++++------- 2 files changed, 155 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a613e41e..d6e01912 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,7 +151,6 @@ libpressio_plugin_file(io/by_extension.cc) libpressio_plugin_file(io/posix.cc) libpressio_plugin_file(domains/malloc.cc) libpressio_plugin_file(domains/nonowning.cc) -# libpressio_plugin_file(metrics/qoi.cc) #optional components created with libpressio_optional_component don't require dependencies #they can be enabled in two (non-exclusive) ways: diff --git a/src/plugins/metrics/qoi.cc b/src/plugins/metrics/qoi.cc index f8234f1c..c08b9d97 100644 --- a/src/plugins/metrics/qoi.cc +++ b/src/plugins/metrics/qoi.cc @@ -1,7 +1,3 @@ -// #include "pressio_options.h" -// #include "libpressio_ext/cpp/metrics.h" -// #include "libpressio_ext/cpp/pressio.h" -// #include "std_compat/memory.h" #include "pressio_options.h" #include "libpressio_ext/cpp/metrics.h" #include "libpressio_ext/cpp/options.h" @@ -9,8 +5,6 @@ #include "libpressio_ext/cpp/data.h" #include "std_compat/memory.h" - -// #include #include #include #include @@ -28,6 +22,108 @@ namespace libpressio { namespace metrics { namespace qoi_ns { +struct qoi_statistics { + double mean; + double min_val; + double max_val; + double median; + double p90; + double p99; + double p999; + double wasserstein_distance; +}; + +qoi_statistics calculate_statistics( + const std::vector& dists, + const std::vector& mass_orig, + const std::vector& mass_dec) { + qoi_statistics stats = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + + if (!dists.empty()) { + double sum = 0.0; + for (size_t i = 0; i < dists.size(); ++i) { + sum += dists[i]; + } + stats.mean = sum / static_cast(dists.size()); + + std::vector sorted_dists = dists; + std::sort(sorted_dists.begin(), sorted_dists.end()); + + size_t n = sorted_dists.size(); + + stats.min_val = sorted_dists[0]; + stats.max_val = sorted_dists[n - 1]; + + if (n % 2 == 0) { + stats.median = (sorted_dists[n/2 - 1] + sorted_dists[n/2]) / 2.0; + } else { + stats.median = sorted_dists[n/2]; + } + + auto percentile = [&sorted_dists, n](double p) -> double { + if (n == 1) return sorted_dists[0]; + double index = p * (n - 1); + size_t lower = static_cast(index); + size_t upper = lower + 1; + if (upper >= n) return sorted_dists[n - 1]; + double fraction = index - lower; + return sorted_dists[lower] * (1.0 - fraction) + sorted_dists[upper] * fraction; + }; + + stats.p90 = percentile(0.90); + stats.p99 = percentile(0.99); + stats.p999 = percentile(0.999); + } + + if (!mass_orig.empty() && !mass_dec.empty()) { + std::vector u = mass_orig; + std::vector v = mass_dec; + std::sort(u.begin(), u.end()); + std::sort(v.begin(), v.end()); + + std::vector all; + all.insert(all.end(), u.begin(), u.end()); + all.insert(all.end(), v.begin(), v.end()); + std::sort(all.begin(), all.end()); + + double w = 0.0; + size_t u_size = u.size(); + size_t v_size = v.size(); + + for (size_t i = 0; i < all.size() - 1; ++i) { + double x = all[i]; + double dx = all[i + 1] - all[i]; + + size_t count_u = 0; + for (size_t j = 0; j < u_size; ++j) { + if (u[j] <= x) { + count_u++; + } else { + break; + } + } + + size_t count_v = 0; + for (size_t j = 0; j < v_size; ++j) { + if (v[j] <= x) { + count_v++; + } else { + break; + } + } + + double U = static_cast(count_u) / static_cast(u_size); + double V = static_cast(count_v) / static_cast(v_size); + + w += std::abs(U - V) * dx; + } + + stats.wasserstein_distance = w; + } + + return stats; +} + class qoi_plugin : public libpressio_metrics_plugin { public: int set_options(pressio_options const& options) override { @@ -37,7 +133,6 @@ class qoi_plugin : public libpressio_metrics_plugin { pressio_options get_options() const override { pressio_options opts; set_meta(opts, "qoi:metric", child_id, child); - // opts.set("qoi:metric_name", metric_name); return opts; } @@ -74,14 +169,10 @@ class qoi_plugin : public libpressio_metrics_plugin { } int begin_compress_impl(const struct pressio_data * input, struct pressio_data const * output) override { - // std::cout << "[QOI] begin_compress_impl: called" << std::endl; return child->begin_compress(input, output); } int end_compress_impl(struct pressio_data const* input, pressio_data const * output, int rc) override { - // Logic to calculate min_v, max_v, p99_v, p999_v, wasserstein_v would go here - - return child->end_compress(input, output, rc); } @@ -134,40 +225,69 @@ class qoi_plugin : public libpressio_metrics_plugin { pressio_options get_metrics_results(pressio_options const & parent) override { pressio_options opt = child->get_metrics_results(parent); - values.clear(); // Clear previous values + values.clear(); + mass_orig.clear(); + mass_dec.clear(); + + bool has_dists = false, has_mass_orig = false, has_mass_dec = false; for (auto const& item : opt) { const std::string& key = item.first; const pressio_option& option = item.second; - // Check if key starts with qoi ("external:results:") if (key.find(qoi) == 0) { - // Try to get as pressio_data (for arrays) - directly from item.second - if (option.holds_alternative() && option.has_value()) { - pressio_data temp_data = option.get_value(); - const double* ptr = static_cast(temp_data.data()); - size_t n = temp_data.num_elements(); - - // Put all values from pressio_data into values vector using pointer - if (ptr != nullptr && n > 0 && temp_data.dtype() == pressio_double_dtype) { - for (size_t i = 0; i < n; ++i) { - values.push_back(ptr[i]); + if (key == "external:results:dists") { + if (option.holds_alternative() && option.has_value()) { + pressio_data temp_data = option.get_value(); + const double* ptr = static_cast(temp_data.data()); + size_t n = temp_data.num_elements(); + if (ptr != nullptr && n > 0 && temp_data.dtype() == pressio_double_dtype) { + values.assign(ptr, ptr + n); + has_dists = true; + } + } + } + else if (key == "external:results:mass_orig") { + if (option.holds_alternative() && option.has_value()) { + pressio_data temp_data = option.get_value(); + const double* ptr = static_cast(temp_data.data()); + size_t n = temp_data.num_elements(); + if (ptr != nullptr && n > 0 && temp_data.dtype() == pressio_double_dtype) { + mass_orig.assign(ptr, ptr + n); + has_mass_orig = true; + } + } + } else if (key == "external:results:mass_dec") { + if (option.holds_alternative() && option.has_value()) { + pressio_data temp_data = option.get_value(); + const double* ptr = static_cast(temp_data.data()); + size_t n = temp_data.num_elements(); + if (ptr != nullptr && n > 0 && temp_data.dtype() == pressio_double_dtype) { + mass_dec.assign(ptr, ptr + n); + has_mass_dec = true; } } - } - // Try to get as double (for single values) - directly from item.second - else if (option.holds_alternative() && option.has_value()) { - double temp_value = option.get_value(); - values.push_back(temp_value); } } } std::cout << "[QOI] Total values in vector: " << values.size() << std::endl; - for (size_t i = 0; i < values.size(); ++i) { - std::cout << "[QOI] values[" << i << "] = " << values[i] << std::endl; - } if (!values.empty()) { + qoi_statistics stats = calculate_statistics(values, mass_orig, mass_dec); + + std::cout << "[QOI] Statistics:" << std::endl; + std::cout << "[QOI] mean: " << stats.mean << std::endl; + std::cout << "[QOI] min: " << stats.min_val << std::endl; + std::cout << "[QOI] max: " << stats.max_val << std::endl; + std::cout << "[QOI] median: " << stats.median << std::endl; + std::cout << "[QOI] p90: " << stats.p90 << std::endl; + std::cout << "[QOI] p99: " << stats.p99 << std::endl; + std::cout << "[QOI] p999: " << stats.p999 << std::endl; + + if (has_mass_orig && has_mass_dec) { + std::cout << "[QOI] wasserstein_distance: " << stats.wasserstein_distance << std::endl; + } + qoi_data = pressio_data::copy(pressio_double_dtype, values.data(), {values.size()}); set(opt, "qoi:data", qoi_data); } @@ -188,15 +308,15 @@ class qoi_plugin : public libpressio_metrics_plugin { private: - std::string qoi = "external:results:"; // Base prefix for JSON results: {"mean": value} -> external:results:mean + std::string qoi = "external:results"; pressio_metrics child = metrics_plugins().build("noop"); std::string child_id = "noop"; pressio_data qoi_data = pressio_data::empty(pressio_byte_dtype, {}); std::vector values; - // Store qoi:data as member (like kth_error.cc) - // double mean = 0.0; + std::vector mass_orig; + std::vector mass_dec; }; pressio_register registration(metrics_plugins(), "qoi", [](){ std::cout << "Registering qoi plugin\n"; return compat::make_unique(); }); -}}} \ No newline at end of file +}}}