FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
quantizer.h
Go to the documentation of this file.
1#pragma once
2
8#include "stage/stage.h"
9#include "fzm_format.h"
10#include "fused/lorenzo_quant/lorenzo_quant.h" // for ErrorBoundMode
11#include "fused/chunk_fusion/chunk_op_params.h" // shared fused-op Params (host packs)
12#include "backend/types.h"
13#include <array>
14#include <cmath>
15#include <cstdint>
16#include <memory>
17#include <cstring>
18#include <limits>
19#include <type_traits>
20
21namespace fz {
22
73static_assert(sizeof(QuantizerConfig) <= FZM_STAGE_CONFIG_SIZE,
74 "QuantizerConfig must fit in FZM_STAGE_CONFIG_SIZE");
75static_assert(sizeof(QuantizerConfig) == 72,
76 "QuantizerConfig archive layout changed; add an explicit compatibility path");
77
137template<typename TInput = float, typename TCode = uint16_t>
138class QuantizerStage : public Stage {
139public:
141 struct Config {
142 double error_bound = 1e-4;
143 int quant_radius = 32768;
144 float outlier_capacity = 0.05f;
150 bool zigzag_codes = false;
152 float outlier_threshold = std::numeric_limits<float>::infinity();
156 bool inplace_outliers = false;
163 bool linear_mode = false;
174 bool power_of_two_bound = false;
190 bool dither = false;
193 uint64_t dither_seed = 0;
200 float dither_strength = 1.0f;
201
202 Config() = default;
203 Config(TInput eb, ErrorBoundMode mode = ErrorBoundMode::ABS,
204 int radius = 32768, float outlier_cap = 0.05f)
205 : error_bound(static_cast<double>(eb)), quant_radius(radius),
206 outlier_capacity(outlier_cap), eb_mode(mode) {}
207 };
208
209 explicit QuantizerStage(const Config& config = Config());
210 ~QuantizerStage() override;
211
213 fz::stream_t stream,
214 MemoryPool* pool,
215 const std::vector<void*>& inputs,
216 const std::vector<void*>& outputs,
217 const std::vector<size_t>& sizes
218 ) override;
219
220 void postStreamSync(fz::stream_t stream) override;
221
226 void onFinalize(size_t estimated_inlen, MemoryPool* pool) override;
227
228 size_t estimateDeviceFootprintBytes(size_t /*estimated_inlen*/) const override {
229 return (isLinearMode() || isInplaceMode()) ? 0 : sizeof(uint32_t);
230 }
231
232 std::string getName() const override { return "Quantizer"; }
233
234 size_t getNumInputs() const override {
235 if (!is_inverse_) return 1;
236 return (isLinearMode() || isInplaceMode()) ? 1 : 3;
237 }
238 size_t getNumOutputs() const override {
239 if (is_inverse_) return 1;
240 return (isLinearMode() || isInplaceMode()) ? 1 : 3;
241 }
242
243 std::vector<std::string> getOutputNames() const override {
244 if (is_inverse_) return {"reconstructed"};
245 if (isLinearMode() || isInplaceMode()) return {"codes"};
246 return {"codes", "outlier_vals", "outlier_idxs"};
247 }
248
249 std::vector<size_t> estimateOutputSizes(
250 const std::vector<size_t>& input_sizes
251 ) const override;
252
253 std::unordered_map<std::string, size_t> getActualOutputSizesByName() const override {
254 auto names = getOutputNames();
255 std::unordered_map<std::string, size_t> result;
256 for (size_t i = 0; i < names.size() && i < actual_output_sizes_.size(); i++)
257 result[names[i]] = actual_output_sizes_[i];
258 return result;
259 }
260 size_t getActualOutputSize(int index) const override {
261 return (index >= 0 && index < static_cast<int>(actual_output_sizes_.size()))
262 ? actual_output_sizes_[index] : 0;
263 }
264
265 void setInverse(bool inverse) override { is_inverse_ = inverse; }
266 bool isInverse() const override { return is_inverse_; }
267
272 FusionSpec getFusionSpec() const override {
273 if (is_inverse_) return {};
274 if (isLinearMode() && !config_.linear_high_precision)
275 return FusionSpec{FusionAccess::Elementwise, 0};
276 if (isInplaceMode() && config_.zigzag_codes &&
277 (config_.eb_mode == ErrorBoundMode::ABS || config_.eb_mode == ErrorBoundMode::NOA))
278 return FusionSpec{FusionAccess::Elementwise, 0};
279 // Split-outlier (3-port) ABS/NOA zigzag quant is Elementwise too: codes flow to the
280 // next stage (port 0), outlier_vals/idxs (ports 1,2) escape as pipeline leaves
281 // that the fused runner fills and the pipeline auto-concatenates. Dither is
282 // excluded (the fused op has no per-element dither path).
283 if (isSplitOutlierFusable()) return FusionSpec{FusionAccess::Elementwise, 0};
284 return {};
285 }
286
292 if (config_.eb_mode == ErrorBoundMode::ABS) {
293 computed_abs_eb_ = resolveUniformBound();
294 if (config_.power_of_two_bound)
295 computed_abs_eb_ = floorPowerOfTwo(computed_abs_eb_);
296 }
297 }
298
303 void primeComputedAbsEb(const void* d_in, size_t scan_n,
304 MemoryPool* pool, fz::stream_t stream);
305 TInput getComputedAbsEb() const { return computed_abs_eb_; }
306 uint32_t getActualOutlierCount() const { return actual_outlier_count_; }
307 bool supportsChunkInverseFusion() const {
308 return std::is_same<TInput, float>::value &&
309 std::is_same<TCode, uint32_t>::value &&
310 !isLinearMode() && config_.zigzag_codes && !config_.dither &&
311 (config_.eb_mode == ErrorBoundMode::ABS ||
312 config_.eb_mode == ErrorBoundMode::NOA);
313 }
318 return (std::is_same<TInput, float>::value || std::is_same<TInput, double>::value) &&
319 std::is_same<TCode, uint32_t>::value &&
320 isLinearMode() && !config_.linear_high_precision &&
321 (config_.eb_mode == ErrorBoundMode::ABS ||
322 config_.eb_mode == ErrorBoundMode::NOA);
323 }
324 void setFusedInverseResult(size_t output_bytes) override {
325 actual_output_sizes_ = {output_bytes};
326 }
327
333 if (!is_inverse_ || !supportsWarpInverseFusion()) return {};
334 return FusionSpec{FusionAccess::Elementwise, 0};
335 }
337 if (!getInverseFusionSpec().fusable()) return {};
338 // Marker op: the linear `code * 2*abs_eb` dequant is a built-in tail of the
339 // warp inverse harness, not a composed device policy. The generic runner
340 // reads the step from getFusedInverseDequantStep(), not from this name.
341 FusedOpDecl d;
342 d.strategy = FusionStrategy::WarpRegister;
343 d.op_name = "LinearDequant";
344 return d;
345 }
346 double getFusedInverseDequantStep() const override {
347 return 2.0 * static_cast<double>(computed_abs_eb_);
348 }
349 double getFusedForwardQuantStep() const override {
350 return 2.0 * static_cast<double>(computed_abs_eb_);
351 }
352
356 FusedOpDecl getFusedOp() const override {
357 if (is_inverse_) return {};
358 // Warp-register (cuSZp): linear float/double quant is the Elementwise loader, for ABS or NOA
359 // (both resolve to one uniform-step absolute bound — the runner primes the NOA
360 // range scan and passes the resolved abs_eb). REL is excluded: it is log-domain
361 // per-value quant, not a single abs_eb, so it can't ride the fused kernel.
362 if ((std::is_same<TInput, float>::value || std::is_same<TInput, double>::value) &&
363 std::is_same<TCode, uint32_t>::value &&
364 isLinearMode() && !config_.linear_high_precision &&
365 (config_.eb_mode == ErrorBoundMode::ABS || config_.eb_mode == ErrorBoundMode::NOA))
366 return FusedOpDecl{FusionStrategy::WarpRegister, "LinearQuant", "", {}};
367 // Chunk policies embed float32 outlier bits in 32-bit codes. A double
368 // quantizer cannot use that representation and must retain staged execution.
369 if (!std::is_same<TInput, float>::value) return {};
370 // Chunk-cooperative (PFPL): inplace+zigzag ABS/NOA float quant.
371 if (isInplaceMode() && config_.zigzag_codes &&
372 (config_.eb_mode == ErrorBoundMode::ABS || config_.eb_mode == ErrorBoundMode::NOA)) {
374 p.ebx2_r = config_.verify_reconstruction
375 ? 0.5f / static_cast<float>(computed_abs_eb_)
376 : 1.0f / (2.0f * static_cast<float>(computed_abs_eb_));
377 p.ebx2 = 2.0f * static_cast<float>(computed_abs_eb_);
378 p.abs_eb = static_cast<float>(computed_abs_eb_);
379 p.radius = static_cast<uint32_t>(config_.quant_radius);
380 p.threshold = config_.outlier_threshold;
381 p.verify_reconstruction = config_.verify_reconstruction ? uint8_t{1} : uint8_t{0};
382 FusedOpDecl d;
383 d.strategy = FusionStrategy::ChunkCooperative;
384 d.op_name = "QuantInplaceZigzag";
385 d.include_header = "fused/chunk_fusion/chunk_fusion.cuh";
386 d.params.resize(sizeof(p));
387 std::memcpy(d.params.data(), &p, sizeof(p));
388 return d;
389 }
390 // Chunk-cooperative (3-port): split-outlier ABS/NOA zigzag float quant. Same
391 // uniform-step params as inplace; the op appends outliers to side buffers
392 // instead of inlining raw bits (see QuantSplitOutlier in chunk_fusion.cuh).
393 if (isSplitOutlierFusable()) {
395 p.ebx2_r = 1.0f / (2.0f * static_cast<float>(computed_abs_eb_));
396 p.ebx2 = 2.0f * static_cast<float>(computed_abs_eb_);
397 p.abs_eb = static_cast<float>(computed_abs_eb_);
398 p.radius = static_cast<uint32_t>(config_.quant_radius);
399 p.threshold = config_.outlier_threshold;
400 p.verify_reconstruction = uint8_t{0};
401 FusedOpDecl d;
402 d.strategy = FusionStrategy::ChunkCooperative;
403 d.op_name = "QuantSplitOutlier";
404 d.include_header = "fused/chunk_fusion/chunk_fusion.cuh";
405 d.params.resize(sizeof(p));
406 std::memcpy(d.params.data(), &p, sizeof(p));
407 return d;
408 }
409 return {};
410 }
411
412 std::vector<FusedAuxOutputDecl> getFusedAuxOutputs() const override {
413 if (is_inverse_ || !isSplitOutlierFusable()) return {};
414 return {
416 static_cast<uint8_t>(getInputDataType()), 1u, 0u, 1u},
418 static_cast<uint8_t>(DataType::UINT32), 1u, 0u, 1u},
419 };
420 }
421
425 fused_outlier_count_set_ = false; // reset per fused compress; set by setFusedSideOutput
426 num_elements_ = c.input_bytes / sizeof(TInput);
427 // Never scan past the real data: the input may be the caller's unpadded buffer.
428 const size_t valid = (c.input_valid_bytes != 0 && c.input_valid_bytes < c.input_bytes)
430 primeComputedAbsEb(c.d_input, valid / sizeof(TInput), c.pool, c.stream);
431 }
432
438 void setFusedSideOutput(int output_index, size_t bytes) override {
439 if (actual_output_sizes_.size() < 3) actual_output_sizes_.resize(3, 0);
440 if (output_index == 1) {
441 actual_outlier_count_ = static_cast<uint32_t>(bytes / sizeof(TInput));
442 actual_output_sizes_[1] = bytes;
443 fused_outlier_count_set_ = true;
444 } else if (output_index == 2) {
445 actual_outlier_count_ = static_cast<uint32_t>(bytes / sizeof(uint32_t));
446 actual_output_sizes_[2] = bytes;
447 fused_outlier_count_set_ = true;
448 }
449 }
450
455 void setDims(const std::array<size_t, 3>& dims) override { dims_ = dims; }
456
457 uint16_t getStageTypeId() const override {
458 return static_cast<uint16_t>(StageType::QUANTIZER);
459 }
460
461 uint8_t getOutputDataType(size_t output_index) const override {
462 if (is_inverse_) return static_cast<uint8_t>(getInputDataType());
463 // Linear mode: codes hold two's-complement signed q — declare the signed type
464 // so the DAG connects cleanly to LorenzoStage<intN>.
465 if (isLinearMode()) return static_cast<uint8_t>(signedOf(getCodeDataType()));
466 if (isInplaceMode()) return static_cast<uint8_t>(getCodeDataType()); // only codes
467 switch (output_index) {
468 case 0: return static_cast<uint8_t>(getCodeDataType());
469 case 1: return static_cast<uint8_t>(getInputDataType());
470 case 2: return static_cast<uint8_t>(DataType::UINT32);
471 default: return static_cast<uint8_t>(DataType::UINT8);
472 }
473 }
474
475 uint8_t getInputDataType(size_t /*input_index*/) const override {
476 return static_cast<uint8_t>(getInputDataType());
477 }
478
479 size_t serializeHeader(size_t output_index, uint8_t* buf, size_t max_size) const override;
480 size_t getMaxHeaderSize(size_t) const override { return sizeof(QuantizerConfig); }
481 void deserializeHeader(const uint8_t* buf, size_t size) override;
482
483 void saveState() override {
484 saved_config_ = config_;
485 saved_num_elements_ = num_elements_;
486 saved_actual_outlier_count_ = actual_outlier_count_;
487 saved_computed_abs_eb_ = computed_abs_eb_;
488 saved_computed_value_base_ = computed_value_base_;
489 saved_actual_output_sizes_ = actual_output_sizes_;
490 }
491
492 void restoreState() override {
493 config_ = saved_config_;
494 num_elements_ = saved_num_elements_;
495 actual_outlier_count_ = saved_actual_outlier_count_;
496 computed_abs_eb_ = saved_computed_abs_eb_;
497 computed_value_base_ = saved_computed_value_base_;
498 actual_output_sizes_ = saved_actual_output_sizes_;
499 }
500
501 void setErrorBound(double eb) { config_.error_bound = eb; }
502 void setQuantRadius(int r) { config_.quant_radius = r; }
503 void setOutlierCapacity(float c) { config_.outlier_capacity = c; }
504 void setErrorBoundMode(ErrorBoundMode m) { config_.eb_mode = m; }
505 void setValueBase(float vb) { config_.precomputed_value_base = vb; }
506 void setZigzagCodes(bool enable) { config_.zigzag_codes = enable; }
508 void setOutlierThreshold(float t) { config_.outlier_threshold = t; }
510 void setInplaceOutliers(bool enable) { config_.inplace_outliers = enable; }
512 void setLinearMode(bool enable) { config_.linear_mode = enable; }
514 void setLinearHighPrecision(bool enable) { config_.linear_high_precision = enable; }
516 void setPowerOfTwoBound(bool enable) { config_.power_of_two_bound = enable; }
519 void setVerifyReconstruction(bool enable){ config_.verify_reconstruction = enable; }
522 void setDither(bool enable) { config_.dither = enable; }
524 void setDitherSeed(uint64_t seed) { config_.dither_seed = seed; }
526 void setDitherStrength(float strength) { config_.dither_strength = strength; }
527
528 TInput getErrorBound() const { return static_cast<TInput>(config_.error_bound); }
529 int getQuantRadius() const { return config_.quant_radius; }
530 ErrorBoundMode getErrorBoundMode() const { return config_.eb_mode; }
531 float getValueBase() const { return config_.precomputed_value_base; }
532 float getOutlierCapacity() const { return config_.outlier_capacity; }
533 bool getZigzagCodes() const { return config_.zigzag_codes; }
534 float getOutlierThreshold() const { return config_.outlier_threshold; }
535 bool getInplaceOutliers() const { return config_.inplace_outliers; }
536 bool getLinearMode() const { return config_.linear_mode; }
537 bool getLinearHighPrecision() const { return config_.linear_high_precision; }
538 bool getPowerOfTwoBound() const { return config_.power_of_two_bound; }
539 bool getVerifyReconstruction() const { return config_.verify_reconstruction; }
540 bool getDither() const { return config_.dither; }
541 uint64_t getDitherSeed() const { return config_.dither_seed; }
542 float getDitherStrength() const { return config_.dither_strength; }
543
544private:
545 Config config_;
546 Config saved_config_;
547 std::array<size_t, 3> dims_ = {0, 1, 1};
548 std::vector<size_t> actual_output_sizes_;
549 std::vector<size_t> saved_actual_output_sizes_;
550 size_t num_elements_ = 0;
551 size_t saved_num_elements_ = 0;
552 uint32_t actual_outlier_count_= 0;
553 uint32_t saved_actual_outlier_count_ = 0;
558 bool fused_outlier_count_set_ = false;
559 bool is_inverse_ = false;
560 TInput computed_abs_eb_ = static_cast<TInput>(1e-4);
561 TInput saved_computed_abs_eb_ = static_cast<TInput>(1e-4);
562 TInput computed_value_base_ = static_cast<TInput>(0);
563 TInput saved_computed_value_base_ = static_cast<TInput>(0);
571 uint32_t* d_outlier_count_scratch_ = nullptr;
574 uint32_t* d_linear_overflow_scratch_ = nullptr;
577 MemoryPool* persistent_pool_ = nullptr;
582 std::weak_ptr<const void> persistent_pool_alive_;
583
584
588 void initOutlierCountScratch(MemoryPool* pool);
589 void initLinearOverflowScratch(MemoryPool* pool);
590
591 // ── execute() kernel-launch helpers ────────────────────────────────────
592 // Each wraps exactly one forward/inverse kernel-instantiation path so
593 // execute() reduces to mode resolution + dispatch. Pure call-site
594 // extraction: no kernel logic, math, or launch parameters changed.
595
597 void launchRelForward(fz::stream_t stream, int grid, int block,
598 const TInput* in, size_t num_elements,
599 float log2eb, float log2eb_r, float opp_eb, float oopp_eb,
600 size_t max_outliers,
601 TCode* codes, TInput* outlier_vals, uint32_t* outlier_idxs);
603 void launchLinearForward(fz::stream_t stream, int grid, int block,
604 const TInput* in, size_t num_elements,
605 TInput ebx2_r, double ebx2_r_f64, TCode* codes);
608 void launchInplaceForward(fz::stream_t stream, int grid, int block,
609 const TInput* in, size_t num_elements,
610 TInput ebx2_r, TInput ebx2, TInput abs_eb,
611 TCode* codes);
613 void launchAbsNoaForward(fz::stream_t stream, int grid, int block,
614 const TInput* in, size_t num_elements,
615 TInput ebx2_r, TInput ebx2, TInput abs_eb,
616 TInput dither_amp, uint64_t dither_seed,
617 size_t max_outliers,
618 TCode* codes, TInput* outlier_vals, uint32_t* outlier_idxs);
619
621 void launchRelInverse(fz::stream_t stream, int grid, int block,
622 const TCode* codes, size_t num_elements,
623 float log2eb, TInput* out);
625 void launchLinearInverse(fz::stream_t stream, int grid, int block,
626 const TCode* codes, size_t num_elements,
627 TInput ebx2, double ebx2_f64, TInput* out);
629 void launchInplaceInverse(fz::stream_t stream, int grid, int block,
630 const TCode* codes, size_t num_elements,
631 TInput ebx2, TInput* out);
633 void launchAbsNoaInverse(fz::stream_t stream, int grid, int block,
634 const TCode* codes, size_t num_elements,
635 TInput ebx2, TInput dither_amp, uint64_t dither_seed,
636 TInput* out);
637
638 bool isInplaceMode() const {
639 return config_.inplace_outliers
640 && config_.eb_mode != ErrorBoundMode::REL;
641 }
642
643 bool isLinearMode() const { return config_.linear_mode; }
644
645 static TInput floorPowerOfTwo(TInput value) {
646 if (!(value > TInput(0)) || !std::isfinite(value))
647 throw std::runtime_error(
648 "QuantizerStage: power_of_two_bound requires a finite positive absolute bound");
649 int exponent = 0;
650 std::frexp(value, &exponent);
651 return std::ldexp(TInput(1), exponent - 1);
652 }
653
654 TInput resolveUniformBound(TInput scale = TInput(1)) const {
655 // Native PFPL's float32 path parses the user bound into float and then
656 // multiplies the float range by that float. Preserve that operation
657 // order when its reconstruction guard is selected: even a one-ULP
658 // difference changes which near-boundary values are embedded raw.
659 if (config_.verify_reconstruction && std::is_same<TInput, float>::value)
660 return static_cast<TInput>(config_.error_bound) * scale;
661 const double resolved = config_.error_bound * static_cast<double>(scale);
662 TInput bound = static_cast<TInput>(resolved);
663 // The strict path must never loosen a decimal/TOML request merely because
664 // its TInput representation rounded upward. f64 compares equal here;
665 // this primarily protects f32.
666 if (config_.linear_high_precision && static_cast<double>(bound) > resolved)
667 bound = std::nextafter(bound, TInput(0));
668 return bound;
669 }
670
671 void applyUniformBoundPolicy(TInput data_abs_max, bool have_data_abs_max);
672
677 bool isSplitOutlierFusable() const {
678 return std::is_same<TInput, float>::value && !is_inverse_
679 && !isInplaceMode() && !isLinearMode()
680 && config_.zigzag_codes && !config_.dither
681 && (config_.eb_mode == ErrorBoundMode::ABS ||
682 config_.eb_mode == ErrorBoundMode::NOA);
683 }
684
687 static DataType signedOf(DataType d) {
688 switch (d) {
689 case DataType::UINT8: return DataType::INT8;
690 case DataType::UINT16: return DataType::INT16;
691 case DataType::UINT32: return DataType::INT32;
692 default: return d;
693 }
694 }
695
696 DataType getInputDataType() const {
697 if (std::is_same<TInput, float>::value) return DataType::FLOAT32;
698 if (std::is_same<TInput, double>::value) return DataType::FLOAT64;
699 return DataType::FLOAT32;
700 }
701 DataType getCodeDataType() const {
702 if (std::is_same<TCode, uint8_t>::value) return DataType::UINT8;
703 if (std::is_same<TCode, uint16_t>::value) return DataType::UINT16;
704 if (std::is_same<TCode, uint32_t>::value) return DataType::UINT32;
705 return DataType::UINT16;
706 }
707 size_t getMaxOutlierCount(size_t n) const {
708 return static_cast<size_t>(std::ceil(n * config_.outlier_capacity));
709 }
710};
711
712extern template class QuantizerStage<float, uint16_t>;
713extern template class QuantizerStage<float, uint32_t>;
714extern template class QuantizerStage<double, uint16_t>;
715extern template class QuantizerStage<double, uint32_t>;
716
717} // namespace fz
POD parameter blocks for the chunk-cooperative device-ops.
Definition mempool.h:82
Definition quantizer.h:138
void setDither(bool enable)
Definition quantizer.h:522
void saveState() override
Definition quantizer.h:483
uint8_t getInputDataType(size_t) const override
Definition quantizer.h:475
uint8_t getOutputDataType(size_t output_index) const override
Definition quantizer.h:461
void setInplaceOutliers(bool enable)
ABS/NOA/PREL: encode outliers in-place (raw input bits in codes array; no scatter buffers).
Definition quantizer.h:510
void setPowerOfTwoBound(bool enable)
Uniform modes: tighten the resolved absolute EB to the next lower power of two.
Definition quantizer.h:516
std::vector< std::string > getOutputNames() const override
Definition quantizer.h:243
void setInverse(bool inverse) override
Definition quantizer.h:265
void deserializeHeader(const uint8_t *buf, size_t size) override
FusedOpDecl getFusedOp() const override
Definition quantizer.h:356
std::vector< FusedAuxOutputDecl > getFusedAuxOutputs() const override
Definition quantizer.h:412
double getFusedForwardQuantStep() const override
Definition quantizer.h:349
size_t estimateDeviceFootprintBytes(size_t) const override
Definition quantizer.h:228
void primeAbsEbForFusion()
Definition quantizer.h:291
void primeComputedAbsEb(const void *d_in, size_t scan_n, MemoryPool *pool, fz::stream_t stream)
void setDims(const std::array< size_t, 3 > &dims) override
Definition quantizer.h:455
FusedOpDecl getInverseFusedOp() const override
Definition quantizer.h:336
void setOutlierThreshold(float t)
ABS/NOA: |x| >= threshold → lossless outlier regardless of bin (LC reference parameter).
Definition quantizer.h:508
void onFinalize(size_t estimated_inlen, MemoryPool *pool) override
void setFusedInverseResult(size_t output_bytes) override
Definition quantizer.h:324
void setFusedSideOutput(int output_index, size_t bytes) override
Definition quantizer.h:438
void setDitherSeed(uint64_t seed)
Seed for the deterministic per-element dither offset (see Config::dither_seed).
Definition quantizer.h:524
std::string getName() const override
Definition quantizer.h:232
size_t serializeHeader(size_t output_index, uint8_t *buf, size_t max_size) const override
uint16_t getStageTypeId() const override
Definition quantizer.h:457
void setVerifyReconstruction(bool enable)
Definition quantizer.h:519
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition quantizer.h:253
bool supportsWarpInverseFusion() const
Definition quantizer.h:317
void setLinearHighPrecision(bool enable)
Linear mode: use double coordinate arithmetic and a strict rounding reserve.
Definition quantizer.h:514
void setDitherStrength(float strength)
Dither offset amplitude as a fraction of abs_eb, in (0,1]; see Config::dither_strength.
Definition quantizer.h:526
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
FusionSpec getInverseFusionSpec() const override
Definition quantizer.h:332
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
size_t getMaxHeaderSize(size_t) const override
Definition quantizer.h:480
void setLinearMode(bool enable)
ABS/NOA: linear / no-outlier mode (cuSZp-style signed codes; see Config::linear_mode).
Definition quantizer.h:512
size_t getActualOutputSize(int index) const override
Definition quantizer.h:260
void postStreamSync(fz::stream_t stream) override
double getFusedInverseDequantStep() const override
Definition quantizer.h:346
void primeFusedForwardState(const FusedPrimeContext &c) override
Definition quantizer.h:424
FusionSpec getFusionSpec() const override
Definition quantizer.h:272
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
@ NOA
Value-range relative bound (norm-of-absolute).
@ ABS
Absolute error bound.
@ REL
Exact per-element point-wise relative bound (QuantizerStage only).
constexpr size_t FZM_STAGE_CONFIG_SIZE
Per-stage serialized config slot (bytes)
Definition fzm_format.h:65
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:142
@ CompactedElements
runtime count * sizeof(element)
Base class interface for all compression stages.
Definition fusion.h:131
A stage's contribution to a generated fused kernel — the device-op it maps to, where its source lives...
Definition fusion.h:161
std::vector< uint8_t > params
POD Params bytes; empty for stateless ops.
Definition fusion.h:165
std::string op_name
device-op type name, e.g. "DiffNegabinary"
Definition fusion.h:163
std::string include_header
header used by the generated source
Definition fusion.h:164
Minimal context a fused runner hands a stage so it can establish the forward-computed state its OWN i...
Definition fusion.h:205
size_t input_valid_bytes
real bytes at d_input; 0 = input_bytes
Definition fusion.h:210
fz::stream_t stream
stream to prime on
Definition fusion.h:209
MemoryPool * pool
scratch pool
Definition fusion.h:208
const void * d_input
device input buffer
Definition fusion.h:206
size_t input_bytes
its size in bytes (logical, chunk-aligned)
Definition fusion.h:207
A stage's fusion contract. Stages that can participate in a fused kernel override Stage::getFusionSpe...
Definition fusion.h:51
Definition quantizer.h:28
uint8_t inplace_outliers
1 if outliers are encoded in-place in the codes array.
Definition quantizer.h:43
double abs_error_bound_f64
Definition quantizer.h:58
uint32_t _pad2
Definition quantizer.h:52
uint8_t linear_mode
1 if linear/no-outlier mode (signed codes, no outlier ports).
Definition quantizer.h:44
uint8_t eb_mode
ErrorBoundMode cast to uint8_t.
Definition quantizer.h:40
uint64_t dither_seed
Deterministic per-element dither seed; meaningful only when dither.
Definition quantizer.h:50
uint32_t outlier_count
Actual number of outliers.
Definition quantizer.h:37
DataType code_type
Quantization code type (1B).
Definition quantizer.h:39
uint8_t zigzag_codes
1 if ABS/NOA codes are zigzag-encoded.
Definition quantizer.h:41
uint32_t num_elements
Total element count.
Definition quantizer.h:36
uint8_t _pad[2]
Alignment padding (dither_seed needs 8-byte alignment) — must be zero.
Definition quantizer.h:49
double value_base_f64
Full-precision value_base; 0 in pre-2026-08-07 headers.
Definition quantizer.h:59
uint8_t power_of_two_bound
1 if the uniform absolute EB was rounded down to a power of two.
Definition quantizer.h:47
uint32_t quant_radius
Quantization radius.
Definition quantizer.h:35
float user_error_bound
Definition quantizer.h:32
DataType input_type
Original input type (1B).
Definition quantizer.h:38
float abs_error_bound
Absolute EB after mode conversion (0 for REL).
Definition quantizer.h:31
float dither_strength
Dither offset amplitude as a fraction of abs_eb, in (0,1]; meaningful only when dither.
Definition quantizer.h:51
float outlier_threshold
ABS/NOA: |x| >= threshold → forced outlier (inf = disabled).
Definition quantizer.h:42
uint8_t dither
1 if "_R"-style dithered reconstruction is enabled (LC QUANT_*_R).
Definition quantizer.h:45
uint8_t linear_high_precision
1 if linear coordinates are evaluated in double precision.
Definition quantizer.h:46
uint8_t verify_reconstruction
1 if in-place quantization verifies the reconstructed value.
Definition quantizer.h:48
float value_base
value_range (NOA); 0 for ABS/REL.
Definition quantizer.h:34
Definition quantizer.h:141
float outlier_threshold
ABS/NOA: |x| >= threshold → lossless outlier (LC reference threshold). Default: ∞.
Definition quantizer.h:152
bool dither
Definition quantizer.h:190
float outlier_capacity
Fraction of input size reserved for outliers.
Definition quantizer.h:144
bool zigzag_codes
Definition quantizer.h:150
bool power_of_two_bound
Definition quantizer.h:174
uint64_t dither_seed
Definition quantizer.h:193
float precomputed_value_base
Pre-computed value_base > 0 to skip the NOA data scan; 0 = auto.
Definition quantizer.h:147
bool inplace_outliers
Definition quantizer.h:156
int quant_radius
Quantization radius.
Definition quantizer.h:143
bool linear_mode
Definition quantizer.h:163
double error_bound
Error bound (interpretation set by eb_mode).
Definition quantizer.h:142
bool verify_reconstruction
Definition quantizer.h:180
bool linear_high_precision
Definition quantizer.h:168
float dither_strength
Definition quantizer.h:200
Definition chunk_op_params.h:28
Backend-neutral GPU type aliases.