Skip to content

Fix 2-D/3-D compressed size missing the rate-array alignment padding - #14

Merged
hyfshishen merged 1 commit into
szcompressor:masterfrom
skyler-ruiter:fix-2d3dcmpsize-padding
Oct 13, 2026
Merged

hyfshishen merged 1 commit into
szcompressor:masterfrom
skyler-ruiter:fix-2d3dcmpsize-padding

Conversation

@skyler-ruiter

Copy link
Copy Markdown
Contributor

Title: Fix 2-D/3-D compressed size missing the rate-array alignment padding

Problem

The 2-D and 3-D compress entry points report

*cmpSize = (size_t)glob_sync + blockNum;

but the kernels place the block payloads after the per-block rate array padded to a
multiple of 4 bytes:

const uint rate_ofs = (blockNum + 3) / 4 * 4;   // src/cuSZp_kernels_{2D,3D}_{f32,f64}.cu

So the reported size is short by (-blockNum) mod 4 bytes (0-3). Any caller that
stores or transfers exactly cmpSize bytes (the example CLI does both: it copies
cmpSize bytes to the host and writes them to the .cuszp file) drops the end of
the stream. Decompression derives offsets from the rate bytes, not from cmpSize, so
it reads the missing bytes as zero. Those final bytes are the most significant bit
plane of the last block with a payload, so up to 16-24 values in that block lose
their top quantization bit and miss the error bound by a power-of-two multiple of
2*eb.

The 1-D entry points are correct: they add the padded count, which matches the 1-D
kernels' offset.

Reproduction (cuSZp v3.0.0 and current master f581dcf)

  • CESM-ATM 1800x3600, -m fixed 2-D, REL 1e-4: blockNum = 225*450 = 101250, 2 bytes
    lost; 16 values exceed the bound, the largest by about 1.3e5 x eb (the CLI's own check,
    which allows 1.1 x eb, reports them).
  • HURR 100x500x500 and S3D 500^3 (3-D): blockNum is 390625 and 1953125, 3 bytes lost.
  • Over a 186-field SDRBench corpus at REL 1e-2/1e-3/1e-4, every one of 362 severe bound
    violations in fixed, plain and outlier modes (2-D and 3-D, f32 and f64) has this cause.
    With the change below, all 362 cells satisfy the bound (worst 1.009 x eb; the only
    remaining overshoots are float64 rounding at <= 1.0000001 x eb). Compressed sizes grow by
    0-3 bytes.

Fix

Report the padded rate-array length in all 12 2-D/3-D compress entry points (fixed,
plain, outlier x 2-D, 3-D x f32, f64):

*cmpSize = (size_t)glob_sync + (blockNum + 3) / 4 * 4;

This matches rate_ofs in the corresponding kernels and the 1-D entry points.

The 2-D and 3-D compress entry points reported glob_sync + blockNum, but the kernels place block payloads after the rate array padded to a multiple of 4 bytes (rate_ofs = (blockNum + 3) / 4 * 4). Callers that store exactly cmpSize bytes lost the last 0-3 bytes, the top bit plane of the last block with a payload, so values there could miss the error bound by a power-of-two multiple of 2*eb. Report the padded length, matching rate_ofs and the 1-D entry points.
@codecov

codecov Bot commented Oct 12, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@hyfshishen
hyfshishen merged commit 9a9645a into szcompressor:master Oct 13, 2026
4 checks passed
@hyfshishen

Copy link
Copy Markdown
Collaborator

Hi Skyler, I just merged the PR. Thanks for the great effort!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants