From db5530fbfd5790e0ab97876ebd7ab852cb4ad763 Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Thu, 18 Sep 2025 14:59:30 -0700 Subject: [PATCH 1/4] harden the code on Windows --- include/sperr_helper.h | 6 ++++++ src/CDF97.cpp | 14 +++++++------- src/CMakeLists.txt | 7 +++++-- src/sperr_helper.cpp | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) mode change 100644 => 100755 include/sperr_helper.h mode change 100644 => 100755 src/CDF97.cpp mode change 100644 => 100755 src/CMakeLists.txt mode change 100644 => 100755 src/sperr_helper.cpp diff --git a/include/sperr_helper.h b/include/sperr_helper.h old mode 100644 new mode 100755 index 4adfbb6e..d54bb3e7 --- a/include/sperr_helper.h +++ b/include/sperr_helper.h @@ -66,6 +66,12 @@ enum class RTNType { // // Helper functions // + +// Allocate and deallocate a chunk of ALIGNED memory, for both UNIX and Windows. +auto aligned_malloc(size_t alignment, size_t size) -> void*; +void aligned_free(void* p); + + // Given a certain length, how many transforms to be performed? auto num_of_xforms(size_t len) -> size_t; diff --git a/src/CDF97.cpp b/src/CDF97.cpp old mode 100644 new mode 100755 index c052fbe0..d609368a --- a/src/CDF97.cpp +++ b/src/CDF97.cpp @@ -13,7 +13,7 @@ sperr::CDF97::~CDF97() { if (m_aligned_buf) - std::free(m_aligned_buf); + sperr::aligned_free(m_aligned_buf); } template @@ -31,11 +31,11 @@ auto sperr::CDF97::copy_data(const T* data, size_t len, dims_type dims) -> RTNTy auto max_col = std::max(std::max(dims[0], dims[1]), dims[2]); if (max_col * sizeof(double) > m_aligned_buf_bytes) { if (m_aligned_buf) - std::free(m_aligned_buf); + sperr::aligned_free(m_aligned_buf); size_t alignment = 32; // 256 bits size_t alloc_chunks = (max_col * 8 + 31) / alignment; m_aligned_buf_bytes = alignment * alloc_chunks; - m_aligned_buf = static_cast(std::aligned_alloc(alignment, m_aligned_buf_bytes)); + m_aligned_buf = static_cast(sperr::aligned_malloc(alignment, m_aligned_buf_bytes)); } auto max_slice = std::max(std::max(dims[0] * dims[1], dims[0] * dims[2]), dims[1] * dims[2]); @@ -58,11 +58,11 @@ auto sperr::CDF97::take_data(vecd_type&& buf, dims_type dims) -> RTNType auto max_col = std::max(std::max(dims[0], dims[1]), dims[2]); if (max_col * sizeof(double) > m_aligned_buf_bytes) { if (m_aligned_buf) - std::free(m_aligned_buf); + sperr::aligned_free(m_aligned_buf); size_t alignment = 32; // 256 bits size_t alloc_chunks = (max_col * 8 + 31) / alignment; m_aligned_buf_bytes = alignment * alloc_chunks; - m_aligned_buf = static_cast(std::aligned_alloc(alignment, m_aligned_buf_bytes)); + m_aligned_buf = static_cast(sperr::aligned_malloc(alignment, m_aligned_buf_bytes)); } auto max_slice = std::max(std::max(dims[0] * dims[1], dims[0] * dims[2]), dims[1] * dims[2]); @@ -406,7 +406,7 @@ void sperr::CDF97::m_dwt3d_one_level(std::array len_xyz) for (size_t y = 0; y < len_xyz[1]; y++) { for (size_t x = 0; x < len_xyz[0]; x += 8) { const size_t xy_offset = y * m_dims[0] + x; - const auto stride = std::min(8ul, len_xyz[0] - x); + const size_t stride = std::min(size_t{8}, len_xyz[0] - x); for (size_t z = 0; z < col_len; z++) { for (size_t i = 0; i < stride; i++) @@ -445,7 +445,7 @@ void sperr::CDF97::m_idwt3d_one_level(std::array len_xyz) for (size_t y = 0; y < len_xyz[1]; y++) { for (size_t x = 0; x < len_xyz[0]; x += 8) { const size_t xy_offset = y * m_dims[0] + x; - const auto stride = std::min(8ul, len_xyz[0] - x); + const size_t stride = std::min(size_t{8}, len_xyz[0] - x); for (size_t z = 0; z < col_len; z++) { for (size_t i = 0; i < stride; i++) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt old mode 100644 new mode 100755 index 275aada3..297489ee --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,8 +33,11 @@ endif() if(ENABLE_AVX2) message(STATUS "AVX2 compilation enabled.") - target_compile_options(SPERR PRIVATE -mavx2 -mfma) - if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(SPERR PRIVATE + "$<$:/arch:AVX2>" + "$<$,$>:-mavx2;-mfma>") + + if(NOT CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|MSVC") message(WARNING "Compiler '${CMAKE_CXX_COMPILER_ID}' might not explicitly support AVX2 flags. Please add them manually if needed.") endif() else() diff --git a/src/sperr_helper.cpp b/src/sperr_helper.cpp old mode 100644 new mode 100755 index edf59931..cdb8dc1c --- a/src/sperr_helper.cpp +++ b/src/sperr_helper.cpp @@ -15,6 +15,25 @@ #include #endif +auto sperr::aligned_malloc(size_t alignment, size_t size) -> void* +{ +#ifdef _WIN32 + return _aligned_malloc(size, alignment); +#else + return std::aligned_alloc(alignment, size); +#endif +} + +void sperr::aligned_free(void* p) +{ +#ifdef _WIN32 + _aligned_free(p); +#else + std::free(p); +#endif +} + + auto sperr::num_of_xforms(size_t len) -> size_t { assert(len > 0); From 5856dc3baed022a99963092744167adcfcf20552 Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Fri, 19 Sep 2025 13:11:17 -0700 Subject: [PATCH 2/4] minor --- src/SPECK2D_INT_ENC.cpp | 4 ++-- src/SPECK_FLT.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SPECK2D_INT_ENC.cpp b/src/SPECK2D_INT_ENC.cpp index aa730ff4..cf0bd411 100644 --- a/src/SPECK2D_INT_ENC.cpp +++ b/src/SPECK2D_INT_ENC.cpp @@ -100,14 +100,14 @@ auto sperr::SPECK2D_INT_ENC::m_decide_I_significance() const -> bool // auto len = m_dims[0] - m_I.start_x; if (len < 16) { - for (auto y = 0; y < m_I.start_y; y++) { + for (auto y = 0u; y < m_I.start_y; y++) { first = m_coeff_buf.data() + y * m_dims[0] + m_I.start_x; if (std::any_of(first, first + len, [thld = m_threshold](auto v) { return v >= thld; })) return true; } } else { - for (auto y = 0; y < m_I.start_y; y++) { + for (auto y = 0u; y < m_I.start_y; y++) { first = m_coeff_buf.data() + y * m_dims[0] + m_I.start_x; if (sperr::any_ge(first, len, m_threshold)) return true; diff --git a/src/SPECK_FLT.cpp b/src/SPECK_FLT.cpp index fb531c50..c9ae961d 100644 --- a/src/SPECK_FLT.cpp +++ b/src/SPECK_FLT.cpp @@ -465,7 +465,7 @@ auto sperr::SPECK_FLT::compress() -> RTNType m_inverse_wavelet_xform(false); // No multi-resolution needed! m_vals_d = m_cdf.release_data(); auto LOS = std::vector(); - LOS.reserve(0.04 * total_vals); // Reserve space to hold about 4% of total values. + LOS.reserve(total_vals / 20); // Reserve space to hold about 5% of total values. for (size_t i = 0; i < total_vals; i++) { auto diff = m_vals_orig[i] - m_vals_d[i]; if (std::abs(diff) > m_quality) From f928176fdc450bb7fd47baf45746804f1488d827 Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Fri, 19 Sep 2025 13:19:19 -0700 Subject: [PATCH 3/4] bump version to 0.8.4 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53ef56a1..186b0587 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14) -project(SPERR VERSION 0.8.3 LANGUAGES CXX DESCRIPTION "Lossy Scientific Compression with SPERR") +project(SPERR VERSION 0.8.4 LANGUAGES CXX DESCRIPTION "Lossy Scientific Compression with SPERR") if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD "20" CACHE STRING "Choose the C++ Standard to use." FORCE) From 671e3699989116b3ae730c49d2d3ddb797197e6a Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Fri, 19 Sep 2025 13:21:38 -0700 Subject: [PATCH 4/4] clang-format --- include/sperr_helper.h | 1 - src/sperr_helper.cpp | 1 - 2 files changed, 2 deletions(-) mode change 100755 => 100644 include/sperr_helper.h mode change 100755 => 100644 src/sperr_helper.cpp diff --git a/include/sperr_helper.h b/include/sperr_helper.h old mode 100755 new mode 100644 index d54bb3e7..8173477b --- a/include/sperr_helper.h +++ b/include/sperr_helper.h @@ -71,7 +71,6 @@ enum class RTNType { auto aligned_malloc(size_t alignment, size_t size) -> void*; void aligned_free(void* p); - // Given a certain length, how many transforms to be performed? auto num_of_xforms(size_t len) -> size_t; diff --git a/src/sperr_helper.cpp b/src/sperr_helper.cpp old mode 100755 new mode 100644 index cdb8dc1c..1dc5a52d --- a/src/sperr_helper.cpp +++ b/src/sperr_helper.cpp @@ -33,7 +33,6 @@ void sperr::aligned_free(void* p) #endif } - auto sperr::num_of_xforms(size_t len) -> size_t { assert(len > 0);