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 <cuda_runtime.h>
12#include <array>
13#include <cmath>
14#include <cstdint>
15#include <cstring>
16#include <limits>
17
18namespace fz {
19
28 float value_base;
29 uint32_t quant_radius;
30 uint32_t num_elements;
31 uint32_t outlier_count;
34 uint8_t eb_mode;
35 uint8_t zigzag_codes;
38 uint8_t _pad[3];
39
41 : abs_error_bound(0.0f), user_error_bound(0.0f), value_base(0.0f),
43 input_type(DataType::FLOAT32), code_type(DataType::UINT16),
44 eb_mode(0), zigzag_codes(0),
45 outlier_threshold(std::numeric_limits<float>::infinity()),
46 inplace_outliers(0), _pad{} {}
47};
48static_assert(sizeof(QuantizerConfig) <= FZM_STAGE_CONFIG_SIZE,
49 "QuantizerConfig must fit in FZM_STAGE_CONFIG_SIZE");
50
96template<typename TInput = float, typename TCode = uint16_t>
97class QuantizerStage : public Stage {
98public:
100 struct Config {
101 float error_bound = 1e-4f;
102 int quant_radius = 32768;
103 float outlier_capacity = 0.05f;
109 bool zigzag_codes = false;
111 float outlier_threshold = std::numeric_limits<float>::infinity();
115 bool inplace_outliers = false;
116
117 Config() = default;
118 Config(TInput eb, ErrorBoundMode mode = ErrorBoundMode::ABS,
119 int radius = 32768, float outlier_cap = 0.05f)
120 : error_bound(static_cast<float>(eb)), quant_radius(radius),
121 outlier_capacity(outlier_cap), eb_mode(mode) {}
122 };
123
124 explicit QuantizerStage(const Config& config = Config());
125
127 cudaStream_t stream,
128 MemoryPool* pool,
129 const std::vector<void*>& inputs,
130 const std::vector<void*>& outputs,
131 const std::vector<size_t>& sizes
132 ) override;
133
134 void postStreamSync(cudaStream_t stream) override;
135
136 std::string getName() const override { return "Quantizer"; }
137
138 size_t getNumInputs() const override {
139 if (!is_inverse_) return 1;
140 return isInplaceMode() ? 1 : 4;
141 }
142 size_t getNumOutputs() const override {
143 if (is_inverse_) return 1;
144 return isInplaceMode() ? 1 : 4;
145 }
146
147 std::vector<std::string> getOutputNames() const override {
148 if (is_inverse_) return {"reconstructed"};
149 if (isInplaceMode()) return {"codes"};
150 return {"codes", "outlier_vals", "outlier_idxs", "outlier_count"};
151 }
152
153 std::vector<size_t> estimateOutputSizes(
154 const std::vector<size_t>& input_sizes
155 ) const override;
156
157 std::unordered_map<std::string, size_t> getActualOutputSizesByName() const override {
158 auto names = getOutputNames();
159 std::unordered_map<std::string, size_t> result;
160 for (size_t i = 0; i < names.size() && i < actual_output_sizes_.size(); i++)
161 result[names[i]] = actual_output_sizes_[i];
162 return result;
163 }
164 size_t getActualOutputSize(int index) const override {
165 return (index >= 0 && index < static_cast<int>(actual_output_sizes_.size()))
166 ? actual_output_sizes_[index] : 0;
167 }
168
169 void setInverse(bool inverse) override { is_inverse_ = inverse; }
170 bool isInverse() const override { return is_inverse_; }
171
172 uint16_t getStageTypeId() const override {
173 return static_cast<uint16_t>(StageType::QUANTIZER);
174 }
175
176 uint8_t getOutputDataType(size_t output_index) const override {
177 if (is_inverse_) return static_cast<uint8_t>(getInputDataType());
178 if (isInplaceMode()) return static_cast<uint8_t>(getCodeDataType()); // only codes
179 switch (output_index) {
180 case 0: return static_cast<uint8_t>(getCodeDataType());
181 case 1: return static_cast<uint8_t>(getInputDataType());
182 case 2: return static_cast<uint8_t>(DataType::UINT32);
183 case 3: return static_cast<uint8_t>(DataType::UINT32);
184 default: return static_cast<uint8_t>(DataType::UINT8);
185 }
186 }
187
188 uint8_t getInputDataType(size_t /*input_index*/) const override {
189 return static_cast<uint8_t>(getInputDataType());
190 }
191
192 size_t serializeHeader(size_t output_index, uint8_t* buf, size_t max_size) const override;
193 size_t getMaxHeaderSize(size_t) const override { return sizeof(QuantizerConfig); }
194 void deserializeHeader(const uint8_t* buf, size_t size) override;
195
196 void saveState() override {
197 saved_config_ = config_;
198 saved_num_elements_ = num_elements_;
199 saved_actual_outlier_count_ = actual_outlier_count_;
200 saved_computed_abs_eb_ = computed_abs_eb_;
201 saved_computed_value_base_ = computed_value_base_;
202 saved_actual_output_sizes_ = actual_output_sizes_;
203 }
204
205 void restoreState() override {
206 config_ = saved_config_;
207 num_elements_ = saved_num_elements_;
208 actual_outlier_count_ = saved_actual_outlier_count_;
209 computed_abs_eb_ = saved_computed_abs_eb_;
210 computed_value_base_ = saved_computed_value_base_;
211 actual_output_sizes_ = saved_actual_output_sizes_;
212 }
213
214 void setErrorBound(TInput eb) { config_.error_bound = static_cast<float>(eb); }
215 void setQuantRadius(int r) { config_.quant_radius = r; }
216 void setOutlierCapacity(float c) { config_.outlier_capacity = c; }
217 void setErrorBoundMode(ErrorBoundMode m) { config_.eb_mode = m; }
218 void setValueBase(float vb) { config_.precomputed_value_base = vb; }
219 void setZigzagCodes(bool enable) { config_.zigzag_codes = enable; }
221 void setOutlierThreshold(float t) { config_.outlier_threshold = t; }
223 void setInplaceOutliers(bool enable) { config_.inplace_outliers = enable; }
224
225 TInput getErrorBound() const { return static_cast<TInput>(config_.error_bound); }
226 int getQuantRadius() const { return config_.quant_radius; }
227 ErrorBoundMode getErrorBoundMode() const { return config_.eb_mode; }
228 float getValueBase() const { return config_.precomputed_value_base; }
229 float getOutlierCapacity() const { return config_.outlier_capacity; }
230 bool getZigzagCodes() const { return config_.zigzag_codes; }
231 float getOutlierThreshold() const { return config_.outlier_threshold; }
232 bool getInplaceOutliers() const { return config_.inplace_outliers; }
233
234private:
235 Config config_;
236 Config saved_config_;
237 std::vector<size_t> actual_output_sizes_;
238 std::vector<size_t> saved_actual_output_sizes_;
239 size_t num_elements_ = 0;
240 size_t saved_num_elements_ = 0;
241 uint32_t actual_outlier_count_= 0;
242 uint32_t saved_actual_outlier_count_ = 0;
243 bool is_inverse_ = false;
244 TInput computed_abs_eb_ = static_cast<TInput>(1e-4);
245 TInput saved_computed_abs_eb_ = static_cast<TInput>(1e-4);
246 float computed_value_base_ = 0.0f;
247 float saved_computed_value_base_ = 0.0f;
248 const void* d_outlier_count_ptr_ = nullptr;
249
250 bool isInplaceMode() const {
251 return config_.inplace_outliers
252 && config_.eb_mode != ErrorBoundMode::REL;
253 }
254
255 DataType getInputDataType() const {
256 if (std::is_same<TInput, float>::value) return DataType::FLOAT32;
257 if (std::is_same<TInput, double>::value) return DataType::FLOAT64;
258 return DataType::FLOAT32;
259 }
260 DataType getCodeDataType() const {
261 if (std::is_same<TCode, uint8_t>::value) return DataType::UINT8;
262 if (std::is_same<TCode, uint16_t>::value) return DataType::UINT16;
263 if (std::is_same<TCode, uint32_t>::value) return DataType::UINT32;
264 return DataType::UINT16;
265 }
266 size_t getMaxOutlierCount(size_t n) const {
267 return static_cast<size_t>(std::ceil(n * config_.outlier_capacity));
268 }
269};
270
271extern template class QuantizerStage<float, uint16_t>;
272extern template class QuantizerStage<float, uint32_t>;
273extern template class QuantizerStage<double, uint16_t>;
274extern template class QuantizerStage<double, uint32_t>;
275
276} // namespace fz
Definition mempool.h:82
Definition quantizer.h:97
void saveState() override
Definition quantizer.h:196
uint8_t getInputDataType(size_t) const override
Definition quantizer.h:188
uint8_t getOutputDataType(size_t output_index) const override
Definition quantizer.h:176
void setInplaceOutliers(bool enable)
ABS/NOA: encode outliers in-place (raw float bits in codes array; no scatter buffers).
Definition quantizer.h:223
std::vector< std::string > getOutputNames() const override
Definition quantizer.h:147
void setInverse(bool inverse) override
Definition quantizer.h:169
void postStreamSync(cudaStream_t stream) override
void deserializeHeader(const uint8_t *buf, size_t size) override
void setOutlierThreshold(float t)
ABS/NOA: |x| >= threshold → lossless outlier regardless of bin (LC reference parameter).
Definition quantizer.h:221
void execute(cudaStream_t stream, MemoryPool *pool, const std::vector< void * > &inputs, const std::vector< void * > &outputs, const std::vector< size_t > &sizes) override
std::string getName() const override
Definition quantizer.h:136
size_t serializeHeader(size_t output_index, uint8_t *buf, size_t max_size) const override
uint16_t getStageTypeId() const override
Definition quantizer.h:172
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition quantizer.h:157
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
size_t getMaxHeaderSize(size_t) const override
Definition quantizer.h:193
size_t getActualOutputSize(int index) const override
Definition quantizer.h:164
Definition stage.h:30
FZM binary file format definitions — structs, enums, and helpers.
Fused Lorenzo predictor and quantizer stage.
Definition fzm_format.h:25
ErrorBoundMode
Definition lorenzo_quant.h:30
@ ABS
Absolute error bound.
@ REL
Global-approximate point-wise relative bound.
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:104
Base class interface for all compression stages.
Definition quantizer.h:25
uint8_t inplace_outliers
1 if outliers are encoded in-place in the codes array.
Definition quantizer.h:37
uint8_t eb_mode
ErrorBoundMode cast to uint8_t.
Definition quantizer.h:34
uint32_t outlier_count
Actual number of outliers.
Definition quantizer.h:31
DataType code_type
Quantization code type (1B).
Definition quantizer.h:33
uint8_t zigzag_codes
1 if ABS/NOA codes are zigzag-encoded.
Definition quantizer.h:35
uint32_t num_elements
Total element count.
Definition quantizer.h:30
uint32_t quant_radius
Quantization radius.
Definition quantizer.h:29
float user_error_bound
Original user-specified EB.
Definition quantizer.h:27
DataType input_type
Original input type (1B).
Definition quantizer.h:32
float abs_error_bound
Absolute EB after mode conversion (0 for REL).
Definition quantizer.h:26
uint8_t _pad[3]
Alignment padding — must be zero.
Definition quantizer.h:38
float outlier_threshold
ABS/NOA: |x| >= threshold → forced outlier (inf = disabled).
Definition quantizer.h:36
float value_base
value_range (NOA); 0 for ABS/REL.
Definition quantizer.h:28
Definition quantizer.h:100
float outlier_threshold
ABS/NOA: |x| >= threshold → lossless outlier (LC reference threshold). Default: ∞.
Definition quantizer.h:111
float outlier_capacity
Fraction of input size reserved for outliers.
Definition quantizer.h:103
bool zigzag_codes
Definition quantizer.h:109
float precomputed_value_base
Pre-computed value_base > 0 to skip the NOA data scan; 0 = auto.
Definition quantizer.h:106
bool inplace_outliers
Definition quantizer.h:115
int quant_radius
Quantization radius.
Definition quantizer.h:102
float error_bound
Error bound (interpretation set by eb_mode).
Definition quantizer.h:101