FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
ginterp_stage.h
Go to the documentation of this file.
1#pragma once
2
11#include "stage/stage.h"
12#include "fzm_format.h"
13#include "fused/lorenzo_quant/lorenzo_quant.h" // for ErrorBoundMode
14
15#include "backend/types.h"
16#include <array>
17#include <cmath>
18#include <cstdint>
19#include <memory>
20#include <cstring>
21#include <string>
22#include <stdexcept>
23#include <type_traits>
24#include <unordered_map>
25#include <vector>
26
27// Forward-declared in the public header so callers don't pull in the
28// cuSZ-Hi type subset. The full definition lives in cusz_type_subset.h,
29// included only inside the stage TU.
31
32namespace fz {
33
35enum class GInterp2DGeometry : uint8_t { Fine16 = 0, Native64 = 1 };
36
42 // ── identity / dims ─────────────────────────────────────────────────────
43 double error_bound;
45 uint32_t quant_radius;
46 uint32_t num_elements;
47 uint32_t outlier_count;
50 uint8_t ndim;
51 uint8_t eb_mode;
52 uint32_t dim_x;
53 uint32_t dim_y;
54 uint32_t dim_z;
55 uint32_t anchor_dim_x;
56 uint32_t anchor_dim_y;
57 uint32_t anchor_dim_z;
58 float user_eb;
59 float value_base;
60
61 // ── resolved INTERPOLATION_PARAMS (phase 2 auto-tune output, 39 B) ──────
62 // Both encoder and decoder must use the exact same intp_param values, so
63 // the resolved params are written here on compress and consumed on decompress.
64 // Layout chosen to mirror `INTERPOLATION_PARAMS` field-for-field; we don't
65 // memcpy the struct directly because its padding is implementation-defined.
66 double intp_alpha;
67 double intp_beta;
68 uint8_t intp_use_md[6];
69 uint8_t intp_use_natural[6];
70 uint8_t intp_reverse[6];
72 uint8_t geometry_2d;
73 uint8_t pad[7];
74
75 // ~96 bytes. Comfortable margin under FZM_STAGE_CONFIG_SIZE (128 B);
76 // the static_assert below is the source of truth.
77
80 input_type(DataType::FLOAT32), code_type(DataType::UINT16),
81 ndim(3), eb_mode(0),
82 dim_x(0), dim_y(1), dim_z(1),
84 user_eb(0.0f), value_base(0.0f),
85 intp_alpha(1.75), intp_beta(4.0),
86 intp_use_md{1, 1, 0, 0, 0, 0},
87 intp_use_natural{0, 0, 0, 0, 0, 0},
88 intp_reverse{0, 0, 0, 0, 0, 0},
90};
91static_assert(sizeof(GInterpConfig) <= FZM_STAGE_CONFIG_SIZE,
92 "GInterpConfig must fit in FZM_STAGE_CONFIG_SIZE");
93
203template <typename TInput = float, typename TCode = uint16_t>
204class GInterpStage : public Stage {
205public:
206 struct Config {
207 float error_bound = 1e-3f;
219 int quant_radius = 0;
220 float outlier_capacity = 0.10f;
224 std::array<size_t, 3> dims = {0, 0, 0};
228 float precomputed_value_base = 0.0f;
245 uint8_t auto_tuning_mode = 0;
246
250 double manual_alpha = 0.0;
252 double manual_beta = 0.0;
253
256 GInterp2DGeometry geometry_2d = GInterp2DGeometry::Fine16;
257
258 Config() = default;
259 };
260
261 explicit GInterpStage(const Config& cfg = Config()) : config_(cfg) {
262 actual_output_sizes_.resize(4, 0);
263 }
264 ~GInterpStage() override;
265
266 // ── Stage interface ──────────────────────────────────────────────────────
268 fz::stream_t stream,
269 MemoryPool* pool,
270 const std::vector<void*>& inputs,
271 const std::vector<void*>& outputs,
272 const std::vector<size_t>& sizes
273 ) override;
274
275 void postStreamSync(fz::stream_t stream) override;
276
282 void onFinalize(size_t estimated_inlen, MemoryPool* pool) override;
283
284 size_t estimateDeviceFootprintBytes(size_t /*estimated_inlen*/) const override {
285 return needsProfilingScratch() ? kProfilingErrCount * sizeof(float) : 0;
286 }
287 size_t estimatePinnedFootprintBytes(size_t /*estimated_inlen*/) const override {
288 return needsProfilingScratch() ? kProfilingErrCount * sizeof(float) : 0;
289 }
290
291 std::string getName() const override { return "GInterp"; }
292 size_t getNumInputs() const override { return is_inverse_ ? 4 : 1; }
293 size_t getNumOutputs() const override { return is_inverse_ ? 1 : 4; }
294
295 std::vector<std::string> getOutputNames() const override {
296 return {"codes", "anchor", "outlier_vals", "outlier_idxs"};
297 }
298
299 std::vector<size_t> estimateOutputSizes(
300 const std::vector<size_t>& input_sizes
301 ) const override;
302
303 std::unordered_map<std::string, size_t> getActualOutputSizesByName() const override {
304 auto names = getOutputNames();
305 std::unordered_map<std::string, size_t> r;
306 for (size_t i = 0; i < names.size() && i < actual_output_sizes_.size(); i++)
307 r[names[i]] = actual_output_sizes_[i];
308 return r;
309 }
310 size_t getActualOutputSize(int index) const override {
311 return (index >= 0 && index < static_cast<int>(actual_output_sizes_.size()))
312 ? actual_output_sizes_[index] : 0;
313 }
314
315 void saveState() override { saved_output_sizes_ = actual_output_sizes_; }
316 void restoreState() override { actual_output_sizes_ = saved_output_sizes_; }
317
318 // ── Setters ──────────────────────────────────────────────────────────────
319 void setErrorBound(float eb) { config_.error_bound = eb; }
320 void setQuantRadius(int radius) { config_.quant_radius = radius; }
321 void setOutlierCapacity(float cap) { config_.outlier_capacity = cap; }
327 config_.eb_mode = resolveApproxRelMode(m, "GInterpStage");
328 }
329 void setValueBase(float v) { config_.precomputed_value_base = v; }
334 void setAutoTuning(uint8_t mode) { config_.auto_tuning_mode = mode; }
335 void set2DGeometry(GInterp2DGeometry geometry) {
336 if (geometry != GInterp2DGeometry::Fine16 &&
337 geometry != GInterp2DGeometry::Native64)
338 throw std::invalid_argument("GInterpStage: unsupported 2-D geometry");
339 config_.geometry_2d = geometry;
340 }
345 void setManualAlphaBeta(double alpha, double beta) {
346 config_.manual_alpha = alpha;
347 config_.manual_beta = beta;
348 }
349 void setDims(const std::array<size_t, 3>& dims) override;
350 void setDims(size_t x, size_t y, size_t z) {
351 setDims(std::array<size_t, 3>{x, y, z});
352 }
353
354 float getErrorBound() const { return config_.error_bound; }
355 int getQuantRadius() const { return config_.quant_radius; }
356 float getOutlierCapacity() const { return config_.outlier_capacity; }
357 ErrorBoundMode getErrorBoundMode() const { return config_.eb_mode; }
358 float getValueBase() const { return config_.precomputed_value_base; }
359 uint8_t getAutoTuningMode() const { return config_.auto_tuning_mode; }
360 GInterp2DGeometry get2DGeometry() const { return config_.geometry_2d; }
361 std::array<size_t, 3> getDims() const { return config_.dims; }
362
363 void setInverse(bool inv) override { is_inverse_ = inv; }
364 bool isInverse() const override { return is_inverse_; }
365
369 int ndim() const {
370 if (config_.dims[2] > 1) return 3;
371 if (config_.dims[1] > 1) return 2;
372 return 1;
373 }
374
375 // ── Type / Serialization ─────────────────────────────────────────────────
376 uint16_t getStageTypeId() const override {
377 return static_cast<uint16_t>(StageType::G_INTERP);
378 }
379
380 uint8_t getOutputDataType(size_t output_index) const override {
381 switch (output_index) {
382 case 0: return static_cast<uint8_t>(codeDataType()); // codes
383 case 1: return static_cast<uint8_t>(inputDataType()); // anchor
384 case 2: return static_cast<uint8_t>(inputDataType()); // outlier_vals
385 case 3: return static_cast<uint8_t>(DataType::UINT32); // outlier_idxs
386 default: return static_cast<uint8_t>(DataType::UINT8);
387 }
388 }
389 uint8_t getInputDataType(size_t /*input_index*/) const override {
390 return static_cast<uint8_t>(inputDataType());
391 }
392
393 size_t serializeHeader(size_t output_index, uint8_t* buf, size_t max_size) const override;
394 void deserializeHeader(const uint8_t* buf, size_t size) override;
395 size_t getMaxHeaderSize(size_t /*output_index*/) const override {
396 return sizeof(GInterpConfig);
397 }
398
415 bool isGraphCompatible() const override {
416 const bool tune_ok = (config_.auto_tuning_mode == 0 ||
417 config_.auto_tuning_mode == 5);
418 const bool radius_ok = config_.quant_radius > 0;
419 const bool eb_ok = (config_.eb_mode == ErrorBoundMode::ABS) ||
420 (config_.precomputed_value_base > 0.0f);
421 const bool mode5_alpha_ok = (config_.auto_tuning_mode != 5) ||
422 (config_.manual_alpha > 0.0);
423 return tune_ok && radius_ok && eb_ok && mode5_alpha_ok;
424 }
425
426private:
427 Config config_;
428 std::vector<size_t> actual_output_sizes_;
429 std::vector<size_t> saved_output_sizes_;
430
431 bool is_inverse_ = false;
432 size_t num_elements_ = 0;
433 uint32_t actual_outlier_count_ = 0;
440 uint32_t* d_outlier_count_scratch_ = nullptr;
441
444 TInput computed_abs_eb_ = 0;
447 float computed_value_base_ = 0.0f;
448
450 std::array<size_t, 3> anchor_dims_ = {0, 0, 0};
451
452 // ── Phase 2: auto-tuning state ──────────────────────────────────────────
455 static constexpr size_t kProfilingErrCount = 36;
456 float* d_profiling_errors_ = nullptr;
457 float* h_profiling_errors_ = nullptr;
461 MemoryPool* persistent_pool_ = nullptr;
466 std::weak_ptr<const void> persistent_pool_alive_;
467
468
473 double resolved_alpha_ = 1.75;
474 double resolved_beta_ = 4.0;
475 uint8_t resolved_use_md_[6] = {1, 1, 0, 0, 0, 0};
476 uint8_t resolved_use_natural_[6] = {0, 0, 0, 0, 0, 0};
477 uint8_t resolved_reverse_[6] = {0, 0, 0, 0, 0, 0};
478
481 bool needsProfilingScratch() const {
482 const uint8_t m = config_.auto_tuning_mode;
483 return m == 1 || m == 2 || m == 3 || m == 4;
484 }
485
488 void initProfilingScratch(MemoryPool* pool);
490 void initOutlierCountScratch(MemoryPool* pool);
494 INTERPOLATION_PARAMS buildIntpParam() const;
495
496 static DataType inputDataType() { return fused::dataTypeOf<TInput>(); }
497 static DataType codeDataType() { return fused::dataTypeOf<TCode>(); }
498 size_t getMaxOutlierCount(size_t n) const {
499 return static_cast<size_t>(std::ceil(n * config_.outlier_capacity));
500 }
501};
502
503extern template class GInterpStage<float, uint8_t>;
504extern template class GInterpStage<float, uint16_t>;
505extern template class GInterpStage<float, uint32_t>;
506extern template class GInterpStage<double, uint8_t>;
507extern template class GInterpStage<double, uint16_t>;
508extern template class GInterpStage<double, uint32_t>;
509
510} // namespace fz
Definition ginterp_stage.h:204
void postStreamSync(fz::stream_t stream) override
size_t serializeHeader(size_t output_index, uint8_t *buf, size_t max_size) const override
size_t getActualOutputSize(int index) const override
Definition ginterp_stage.h:310
void setDims(const std::array< size_t, 3 > &dims) override
uint8_t getInputDataType(size_t) const override
Definition ginterp_stage.h:389
uint8_t getOutputDataType(size_t output_index) const override
Definition ginterp_stage.h:380
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition ginterp_stage.h:303
size_t getMaxHeaderSize(size_t) const override
Definition ginterp_stage.h:395
void setAutoTuning(uint8_t mode)
Definition ginterp_stage.h:334
void onFinalize(size_t estimated_inlen, MemoryPool *pool) override
bool isGraphCompatible() const override
Definition ginterp_stage.h:415
void setManualAlphaBeta(double alpha, double beta)
Definition ginterp_stage.h:345
size_t estimateDeviceFootprintBytes(size_t) const override
Definition ginterp_stage.h:284
std::vector< std::string > getOutputNames() const override
Definition ginterp_stage.h:295
void saveState() override
Definition ginterp_stage.h:315
uint16_t getStageTypeId() const override
Definition ginterp_stage.h:376
int ndim() const
Definition ginterp_stage.h:369
void setErrorBoundMode(ErrorBoundMode m)
Definition ginterp_stage.h:326
void execute(fz::stream_t stream, MemoryPool *pool, const std::vector< void * > &inputs, const std::vector< void * > &outputs, const std::vector< size_t > &sizes) override
void setInverse(bool inv) override
Definition ginterp_stage.h:363
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
void deserializeHeader(const uint8_t *buf, size_t size) override
size_t estimatePinnedFootprintBytes(size_t) const override
Definition ginterp_stage.h:287
std::string getName() const override
Definition ginterp_stage.h:291
Definition mempool.h:82
Definition stage.h:31
FZM binary file format definitions — structs, enums, and helpers.
Fused Lorenzo predictor and quantizer stage.
Definition dag.h:24
ErrorBoundMode
Definition lorenzo_quant.h:42
@ ABS
Absolute error bound.
ErrorBoundMode resolveApproxRelMode(ErrorBoundMode mode, const char *stage_name)
Definition lorenzo_quant.h:63
constexpr size_t FZM_STAGE_CONFIG_SIZE
Per-stage serialized config slot (bytes)
Definition fzm_format.h:65
@ G_INTERP
Spline interpolation predictor + quantizer (cuSZ-Hi G-Interp)
GInterp2DGeometry
Selects the two supported 2-D spline geometries. 3-D always uses 16^3.
Definition ginterp_stage.h:35
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:142
Base class interface for all compression stages.
Definition cusz_type_subset.h:32
Definition ginterp_stage.h:41
float user_eb
Original user-specified bound (before mode conversion).
Definition ginterp_stage.h:58
uint8_t eb_mode
ErrorBoundMode cast to uint8_t.
Definition ginterp_stage.h:51
uint8_t auto_tuning_mode
0=off, 1=cheap, 3=full, 4=full+alpha sweep, 5+=manual α/β.
Definition ginterp_stage.h:71
float value_base
value_range (NOA) / max(|data|) (REL) used in conversion.
Definition ginterp_stage.h:59
uint8_t intp_use_md[6]
Resolved use_md[level], booleans as u8.
Definition ginterp_stage.h:68
uint32_t dim_x
X (fast) dimension.
Definition ginterp_stage.h:52
uint32_t anchor_dim_x
Anchor grid X extent.
Definition ginterp_stage.h:55
uint8_t geometry_2d
0=fine16 (legacy), 1=native64.
Definition ginterp_stage.h:72
uint8_t pad[7]
Reserved; keep the serialized struct size fixed.
Definition ginterp_stage.h:73
double error_bound
Definition ginterp_stage.h:43
uint32_t dim_z
Z dimension.
Definition ginterp_stage.h:54
double intp_alpha
Resolved alpha (auto-tuned from rel_eb or fixed).
Definition ginterp_stage.h:66
uint32_t num_elements
Total element count (= dim_x*dim_y*dim_z).
Definition ginterp_stage.h:46
uint32_t anchor_dim_y
Anchor grid Y extent.
Definition ginterp_stage.h:56
uint32_t outlier_count
Actual outlier count (post-execute).
Definition ginterp_stage.h:47
uint32_t anchor_dim_z
Anchor grid Z extent.
Definition ginterp_stage.h:57
double intp_beta
Resolved beta (default 4.0).
Definition ginterp_stage.h:67
uint32_t quant_radius
Quantization radius (codes lie in [0, 2*radius)).
Definition ginterp_stage.h:45
DataType code_type
Quant code type (1 B).
Definition ginterp_stage.h:49
uint8_t ndim
Spatial dimensionality (2 or 3).
Definition ginterp_stage.h:50
uint32_t dim_y
Y dimension.
Definition ginterp_stage.h:53
DataType input_type
Float input type (1 B).
Definition ginterp_stage.h:48
Backend-neutral GPU type aliases.