|
FZGPUModules 2.0
GPU-accelerated modular compression pipelines
|
Status: Implemented (v2.0)
Human-readable TOML files that fully describe a compression pipeline: the DAG (topology), stage types and parameters, and pipeline-level settings. A config file can reconstruct an identical pipeline without writing any C++ code.
Load a config and compress data:
For best results – especially when using memory_strategy = "PREALLOCATE" – pass the input size to the constructor before calling loadConfig(). This lets finalize() size buffers correctly rather than relying on a 1-byte placeholder.
Alternatively, the single-argument constructor can be used when MINIMAL strategy is sufficient and pool sizing from the .toml is acceptable:
[!IMPORTANT] When using
memory_strategy = "PREALLOCATE"(required for CUDA Graph capture), always use the constructor +loadConfig()pattern so the pipeline receives the realinput_bytesbeforefinalize()runs preallocations.
Build programmatically, then save for later reuse:
Load an existing config and update a parameter before reuse: Not supported – loadConfig() calls finalize() internally, and finalized pipelines are immutable. Edit the .toml file directly to change parameters.
A config file has one [pipeline] table and one or more [[stage]] entries (an array of tables).
All keys are optional. Absent keys use the pipeline constructor defaults.
| Key | Type | Default | Description |
|---|---|---|---|
| input_size | integer | 0 | Input buffer size hint in bytes. Used for pool sizing at finalize(). |
| dims | array of 3 integers | [0, 1, 1] | Spatial dimensions [x, y, z]. x=0 means infer from input_size. Used by LorenzoND kernels. |
| memory_strategy | string | "MINIMAL" | "MINIMAL" or "PREALLOCATE". |
| pool_multiplier | float | 3.0 | Pool capacity = input_size x pool_multiplier. Relevant for PREALLOCATE. |
| num_streams | integer | 1 | Number of CUDA streams for multi-stream execution. |
| primary_source | string | "" (unset) | Stage name whose inverse output decompress() returns. Only needed when __external__ (see below) creates more than one source stage; unset uses the sole/first-discovered source. |
Stages are processed in file order. Each [[stage]] table describes one node in the pipeline DAG.
Required keys (all stages):
| Key | Type | Description |
|---|---|---|
| name | string | A unique local identifier used in inputs[].from references. |
| type | string | Stage class to instantiate (see Stage Types below). |
Optional key (non-source stages):
| Key | Type | Description |
|---|---|---|
| inputs | array of inline tables | Upstream connections. Each element is { from = "<name>" } or { from = "<name>", port = "<output_name>" }. Stages with no inputs key are pipeline sources. |
If port is omitted it defaults to "output" (the single-output port name for all stages except Lorenzo, which uses named ports "codes", "outlier_errors", "outlier_indices", and "outlier_count").
{ from = "__external__" } is a reserved entry, not a stage reference: it binds the pipeline's raw input directly to this port (Pipeline::bindExternalInput()), even when the same stage's inputs array also has a normal { from = "<name>" } entry at another position — needed by Cdf97OutlierCorrect below, whose raw-field port and codes port come from two different places. Position in the array matters, same as for a real connection. When this creates more than one source stage in the pipeline, set [pipeline].primary_source = "<name>" to say which stage's inverse output decompress() should return (see the SPERR pipeline example below).
The type string in a [[stage]] table selects the stage class. Each stage's settings, ports, and constraints — including every key accepted in its [stage.settings] table — are documented on that stage's own reference page; the TOML key for a setting is the snake_case form of its C++ setter (for example setBlockSize(32) is block_size = 32).
TOML type | Stage class | Reference |
|---|---|---|
Lorenzo | LorenzoStage | LorenzoStage |
LorenzoQuant | LorenzoQuantStage | LorenzoQuantStage |
AdaptiveLorenzo | AdaptiveLorenzoStage | AdaptiveLorenzoStage |
TiledLorenzo | TiledLorenzoStage | TiledLorenzoStage |
Difference | DifferenceStage | DifferenceStage |
Quantizer | QuantizerStage | QuantizerStage |
Zigzag | ZigzagStage | ZigzagStage |
Negabinary | NegabinaryStage | NegabinaryStage |
ADM | ADMStage | ADMStage |
LogTransform | LogTransformStage | LogTransformStage |
Bitshuffle | BitshuffleStage | BitshuffleStage |
TUPL | TUPLStage | TUPLStage |
RLE | RLEStage | RLEStage |
RZE | RZEStage | RZEStage |
RRE | RREStage | RREStage |
RARE | RAREStage | RAREStage |
RAZE | RAZEStage | RAZEStage |
CLOG | CLOGStage | CLOGStage |
HCLOG | HCLOGStage | HCLOGStage |
Bitpack | BitpackStage | BitpackStage |
AdaptiveBitpack | AdaptiveBitpackStage | AdaptiveBitpackStage |
Huffman | HuffmanStage | HuffmanStage |
ANS | ANSStage | ANSStage |
GPULZ | GPULZStage | GPULZStage |
GInterp | GInterpStage | GInterpStage |
BitplaneRZE | BitplaneRZEStage | BitplaneRZEStage |
SZx | SZxStage | SZxStage |
SZp | SZpStage | SZpStage |
Merge | MergeStage | MergeStage |
ROIBinSplit | ROIBinSplitStage | ROIBinSplitStage |
For a cuSZp-style Quantizer with a strict requested bound, set linear_mode = true and linear_high_precision = true. The optional power_of_two_bound = true rounds the resolved ABS/NOA/PREL absolute bound downward to a power of two; it is therefore a tighter, separately labelled rate-distortion configuration. See the Quantizer reference for constraints and effective-bound semantics.
CDF 9/7 biorthogonal wavelet transform (SPERR's DWT front-half). Lossless, invertible, size-preserving float -> float basis change – not itself lossy, feeds a Quantizer. No inputs key needed when it's the pipeline's only true source (the common case).
| Key | Type | Default | Description |
|---|---|---|---|
| data_type | string | "float32" | "float32" or "float64". float64 reproduces SPERR's coefficients bit-for-bit. |
GPU-parallel "wavefront" SPECK-like bit-plane coder (2-D only). Takes signed int32 codes – the same convention Quantizer's linear_mode = true emits.
No tunable keys – dims, threshold, and the tree/magnitude split point are all pipeline/data-derived.
Sparse exact outlier correction: turns CDF97+Quantizer's reported error bound into an actually guaranteed one (quantizing DWT coefficients alone does not bound the reconstructed field's pointwise error – see stage_outlier_correct). Needs the raw field bound to one input port via { from = "__external__" } and the paired Quantizer's codes on the other, in that order (see the inputs note above) – see the SPERR pipeline example below.
| Key | Type | Default | Description |
|---|---|---|---|
| error_bound | float | 1e-4 | MUST equal the paired Quantizer stage's own error_bound exactly (ABS mode only – rel_range/NOA bounds must be converted to absolute externally before setting this). |
Lorenzo predictor with zigzag codes feeding into Bitshuffle and RZE.
The PFPL (Predictor-Free Pipeline) preset – direct-value quantizer with relative error bound, followed by Difference -> Bitshuffle -> RZE. This is the examples/presets/pfpl.toml configuration.
Load it via the CLI:
CDF 9/7 DWT -> Quantizer -> sparse outlier correction -> SPECK2D. Unlike the two examples above, this pipeline has two source stages (dwt, a pure source with no inputs key, and correct, bound to the raw input via { from = "__external__" } alongside its normal quant connection) – primary_source says which one's reconstruction decompress() returns. This is examples/presets/sperr_gpu.toml; see stage_outlier_correct for why the pipeline needs this stage at all (a plain CDF97 -> Quantizer -> SPECK2D chain does not guarantee its reported error bound).
fzgmod-cli --list-stages for the authoritative list from this build. Custom stages written outside the library require a manual addStage() / connect() / finalize() call chain (or a PR to add the type to kStageRegistry in config.cpp).{ from = "__external__" }, primary_source) are representable, but the [pipeline] table still has exactly one input_size and one dims triple – every source reads the same external buffer (see Pipeline::bindExternalInput()), there is no way to express multiple different external inputs in this format.