|
FZGPUModules 2.0
GPU-accelerated modular compression pipelines
|
This page is a concise reference for the fz::Pipeline class — the primary public interface. For context on how these pieces fit together see the Architecture Overview. For per-stage configuration options see the Stage Reference.
Every pipeline follows the same call sequence:
finalize() is the dividing line. Configuration calls go before it; execution calls go after.
Defined in include/pipeline/dag.h.
| Value | Behavior |
|---|---|
MINIMAL | Allocate buffers on demand; free each one as soon as its last consumer reads it. Lowest peak GPU memory. |
PREALLOCATE | Allocate all buffers during finalize(). Required for CUDA Graph capture. Enables buffer coloring for lower memory footprint. |
Defined in modules/fused/lorenzo_quant/lorenzo_quant.h. Used by LorenzoQuantStage and QuantizerStage.
| Value | Meaning | Notes |
|---|---|---|
ABS | Absolute error — abs(x_orig - x_recon) ≤ eb | Useful when data is homogenous in magnitude (preserve big picture) |
REL | Global approximate point-wise relative — abs(error) / abs(x_orig) ≤ eb (approximately) | High level detail close to zero, but higher error with larger values |
NOA | Value-range relative — abs(error) / value_range ≤ eb (norm-of-absolute) | Useful for single bounds over multiple datasets |
| Call | Purpose |
|---|---|
setDims(x)setDims(x, y, z) | Spatial dimensions of the input data. Push dims before addStage() for Lorenzo-family stages. |
setMemoryStrategy(strategy) | Switch between MINIMAL and PREALLOCATE. |
setNumStreams(n) | Number of parallel CUDA streams for level-based execution (default: 4). |
enableGraphMode(true) | Enable CUDA Graph capture mode. Requires PREALLOCATE. |
setWarmupOnFinalize(true) | Auto-run warmup() at the end of finalize(). |
setColoringEnabled(false) | Disable buffer coloring (useful when inspecting buffers with a memory checker). |
enableBoundsCheck(true) | Enable runtime buffer-overwrite detection (always active in debug builds). |
Important: Call setDims() before addStage() for any Lorenzo-family stage. The dims are pushed into the stage at add-time and again at finalize().
The pipeline holds the output buffer. Do not cudaFree it.
Pre-allocate the buffer; the pipeline writes into it.
getMaxCompressedSize(input_bytes) returns a tight upper bound safe to use as the buffer capacity.
Use one Pipeline instance per concurrent stream. Note: RZE/RRE/Huffman/AdaptiveBitpack inverse stages do a blocking device→host header read inside execute() that this cannot remove — for full overlap of those pipelines, drive each slot from its own host thread.
Sizing helpers:
| Call | Returns |
|---|---|
getMaxCompressedSize(input_bytes) | Upper-bound on compressed output size |
getLastUncompressedSize() | Original input size from the most recent compress() call |
| Buffer | Owner | Rule |
|---|---|---|
Input (d_input) | Caller | Pipeline borrows; never freed by the library |
| Compressed output (pool-owned) | Pipeline | Do not cudaFree |
| Decompressed output (pool-owned, default) | Pipeline | Do not cudaFree |
| Decompressed output (caller-owned) | Caller | Must cudaFree |
File decompress (decompressFromFile static) | Caller | Must cudaFree |
File decompress (decompressFromFileInstance) | Depends on setPoolManagedDecompOutput() | Same rules as decompress() |
Memory decompress (decompressFromMemory) | Depends on setPoolManagedDecompOutput() | Same rules as decompress() |
See the FZM File Format page for the full file header specification.
A pipeline that only ever decompresses blobs produced elsewhere — e.g. K streaming slots reading independently-compressed blocks — does not need a throwaway compress() over dummy data to become ready. The in-memory decompress() path otherwise depends on state a forward compress() leaves on the instance: the archive layout and the data-dependent inverse metadata that is not in the raw blob (the HuffmanStage symbol count, the quantizer outlier count — which changes block to block). Carry that metadata in a small in-memory header instead:
serializeHeaderToMemory() requires a prior compress(); returns the FZM core+stage+buffer header as host bytes (no payload). The header is per-blob because the outlier count varies block to block.decompressFromMemory() fuses primeInverseFromHeader() + decompress(); output ownership follows setPoolManagedDecompOutput() exactly as decompress() does.primeInverseFromHeader(header...) then decompress(blob...)).prepareInverse(uncompressed_size) needs no header at all.examples/decode_only_slots.cpp.CUDA Graph capture records the entire compression pass as a replayable graph, eliminating CPU kernel-launch overhead on repeated calls with the same pipeline.
Call compress() only after captureGraph(); use the same stream for capture and replay.
Requirements: PREALLOCATE strategy, non-zero input size at construction, all stages graph-compatible, single-source pipeline. Incompatible with the caller-owned compress() overload.
| Call | Purpose |
|---|---|
pipeline.printPipeline() | Print stage graph, buffer assignments, and execution levels |
pipeline.enableProfiling(true) | Enable per-stage GPU timing |
pipeline.getLastPerfResult() | Per-stage timing from the last compress/decompress |
pipeline.getPeakMemoryUsage() | Peak pool bytes from the last run |
pipeline.getCurrentMemoryUsage() | Live pool bytes right now |
pipeline.isMemPoolFallbackMode() | True if the CUDA pool fell back to cudaMalloc (e.g. vGPU) |
pipeline.reset(stream) | Free non-persistent buffers and reset state for re-use |
"codes", not the default "output".cudaFree compress output or default decompress output.finalize().The stable public API (source-compatible across 1.x) is everything reachable from include/fzgpumodules.h: Pipeline, Stage, StageFactory, FZM file structs, MemoryPool public interface, and the MemoryStrategy / ErrorBoundMode enums.
Anything under src/, kernel implementations in modules/*.cu, allocation heuristics, pool sizing, buffer-coloring details, and logging output text may change in any release without being treated as breaking.
A major version bump is required when:
Stage virtual method in a way that breaks custom stagesMinor bumps cover backward-compatible additions (new methods, overloads, optional fields with safe defaults). Patch bumps cover bug fixes, documentation fixes, and non-behavioral cleanup.
No ABI compatibility guarantee is made across any release — recompile downstream code against the library version in use.
StageType enum values are serialized in .fzm files — existing values must never be renumbered or reused, even after a stage is removed. Adding, removing, or changing any Stage virtual method signature is a breaking change and requires a major-version bump.
Use when opening a PR that touches a public header:
include/?Stage virtual method signatures or behavioral contracts?If any answer is "yes" and the change is not backward-compatible, schedule it as a major-version bump.