21#include <unordered_map>
36 uint8_t blocks_per_tile;
37 uint8_t enable_order2;
38 uint8_t enable_centering;
41 uint32_t num_elements;
42 double abs_error_bound_f64;
48 enable_centering(1),
eb_mode(0), reserved{0, 0, 0}, num_elements(0),
52 "FusedQuantAdaptiveLorenzoConfig must fit in FZM_STAGE_CONFIG_SIZE");
85template<
typename T =
int32_t>
87 static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
88 "FusedQuantAdaptiveLorenzoStage requires a signed integer residual type");
91 uint32_t coder_block_size = 32;
92 uint32_t blocks_per_tile = 8;
93 bool enable_order2 =
true;
94 bool enable_centering =
true;
96 double error_bound = 1e-3;
103 float precomputed_value_base = 0.0f;
111 bool isInverse()
const override {
return is_inverse_; }
113 uint32_t getTileSize()
const {
114 return config_.coder_block_size * config_.blocks_per_tile;
117 void setErrorBound(
double eb) { config_.error_bound = eb; }
121 void setValueBase(
float value_base) { config_.precomputed_value_base = value_base; }
122 double getErrorBound()
const {
return config_.error_bound; }
123 ErrorBoundMode getErrorBoundMode()
const {
return config_.eb_mode; }
131 if (!decl.valid() || !decl.additive ||
132 (decl.kind != EncodingOracleKind::PlainFixedRateBitpack &&
133 decl.kind != EncodingOracleKind::AdaptiveFixedRateBitpack) ||
135 decl.unit_elems != config_.coder_block_size) {
138 bound_oracle_ = decl;
139 has_bound_oracle_ =
true;
143 bool hasBoundEncodingOracle()
const {
return has_bound_oracle_; }
145 return has_bound_oracle_ ? bound_oracle_.kind
146 : EncodingOracleKind::PlainFixedRateBitpack;
150 if (is_inverse_ || !has_bound_oracle_)
return {};
151 return FusionSpec{FusionAccess::TileSelector, getTileSize(),
152 config_.coder_block_size};
159 static_cast<uint8_t
>(DataType::UINT8), getTileSize(),
162 static_cast<uint8_t
>(getElementDataType()), getTileSize(),
170 const std::vector<void*>& inputs,
171 const std::vector<void*>& outputs,
172 const std::vector<size_t>& sizes
175 std::string
getName()
const override {
return "FusedQuantAdaptiveLorenzo"; }
176 size_t getNumInputs()
const override {
return is_inverse_ ? 3 : 1; }
177 size_t getNumOutputs()
const override {
return is_inverse_ ? 1 : 3; }
180 return {
"output",
"modes",
"means"};
193 const std::vector<size_t>& input_sizes
197 const std::vector<size_t>& input_sizes
199 if (input_sizes.empty())
return is_inverse_ ? std::vector<size_t>{0}
200 : std::vector<size_t>{0, 0, 0};
201 if (is_inverse_)
return {input_sizes[0] /
sizeof(T) *
sizeof(
float)};
202 const size_t n = input_sizes[0] /
sizeof(float);
203 const size_t tiles = numTiles(n);
204 return {n *
sizeof(T), (tiles + 3) / 4, tiles *
sizeof(T)};
207 void saveState()
override { saved_output_sizes_ = actual_output_sizes_; }
208 void restoreState()
override {
209 if (!saved_output_sizes_.empty()) actual_output_sizes_ = saved_output_sizes_;
212 std::unordered_map<std::string, size_t>
215 std::unordered_map<std::string, size_t> r;
216 for (
size_t i = 0; i < names.size() && i < actual_output_sizes_.size(); ++i)
217 r[names[i]] = actual_output_sizes_[i];
222 return (index >= 0 && index <
static_cast<int>(actual_output_sizes_.size()))
223 ? actual_output_sizes_[index] : 0;
227 if (actual_output_sizes_.size() < 3) actual_output_sizes_.resize(3, 0);
228 if (output_index == 1 || output_index == 2)
229 actual_output_sizes_[
static_cast<size_t>(output_index)] = bytes;
237 if (is_inverse_)
return static_cast<uint8_t
>(DataType::FLOAT32);
238 return static_cast<uint8_t
>(output_index == 1 ? DataType::UINT8
239 : getElementDataType());
242 if (!is_inverse_)
return static_cast<uint8_t
>(DataType::FLOAT32);
243 return static_cast<uint8_t
>(input_index == 1 ? DataType::UINT8
244 : getElementDataType());
249 throw std::runtime_error(
"FusedQuantAdaptiveLorenzoStage: header buffer too small");
252 cfg.blocks_per_tile =
static_cast<uint8_t
>(config_.blocks_per_tile);
253 cfg.enable_order2 = config_.enable_order2 ? 1u : 0u;
254 cfg.enable_centering = config_.enable_centering ? 1u : 0u;
255 cfg.
eb_mode =
static_cast<uint8_t
>(config_.eb_mode);
256 cfg.num_elements =
static_cast<uint32_t
>(num_elements_);
257 cfg.abs_error_bound_f64 = computed_abs_eb_;
260 std::memcpy(buf, &cfg,
sizeof(cfg));
266 throw std::runtime_error(
"FusedQuantAdaptiveLorenzoStage: header too small");
268 std::memcpy(&cfg, buf,
sizeof(cfg));
270 config_.blocks_per_tile = cfg.blocks_per_tile;
271 config_.enable_order2 = (cfg.enable_order2 != 0);
272 config_.enable_centering = (cfg.enable_centering != 0);
274 num_elements_ = cfg.num_elements;
275 computed_abs_eb_ = cfg.abs_error_bound_f64;
287 bool has_bound_oracle_ =
false;
288 bool is_inverse_ =
false;
289 size_t num_elements_ = 0;
292 double computed_abs_eb_ = 0.0;
293 double computed_value_base_ = 0.0;
294 std::vector<size_t> actual_output_sizes_{0, 0, 0};
295 std::vector<size_t> saved_output_sizes_;
299 uint8_t* d_modes_dense_ =
nullptr;
300 T* d_means_dense_ =
nullptr;
301 uint32_t* d_flags_ =
nullptr;
302 uint32_t* d_offsets_ =
nullptr;
303 size_t scratch_tiles_ = 0;
304 MemoryPool* scratch_pool_ =
nullptr;
305 size_t pending_tiles_ = 0;
310 T* d_inverse_codes_ =
nullptr;
311 size_t inverse_codes_elems_ = 0;
312 MemoryPool* inverse_scratch_pool_ =
nullptr;
314 size_t ensureScratch(
size_t num_tiles, MemoryPool* pool, fz::stream_t stream);
315 size_t ensureInverseScratch(
size_t n, MemoryPool* pool, fz::stream_t stream);
316 void releaseScratch();
318 size_t numTiles(
size_t n)
const {
319 const size_t t = getTileSize();
320 return (n + t - 1) / t;
323 void validate()
const {
324 if (config_.coder_block_size != 32)
325 throw std::invalid_argument(
326 "FusedQuantAdaptiveLorenzoStage: coder_block_size must be 32");
327 if (config_.blocks_per_tile < 1 || config_.blocks_per_tile > 32)
328 throw std::invalid_argument(
329 "FusedQuantAdaptiveLorenzoStage: blocks_per_tile must be in [1, 32], got "
330 + std::to_string(config_.blocks_per_tile));
333 static DataType getElementDataType() {
return fused::dataTypeOf<T>(); }
336extern template class FusedQuantAdaptiveLorenzoStage<int32_t>;
Per-tile adaptive multi-order Lorenzo predictor with centering. Lossless.
Definition quant_adaptive_lorenzo_stage.h:86
void postStreamSync(fz::stream_t stream) override
size_t getActualOutputSize(int index) const override
Definition quant_adaptive_lorenzo_stage.h:221
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 quant_adaptive_lorenzo_stage.h:110
FusionSpec getFusionSpec() const override
Definition quant_adaptive_lorenzo_stage.h:149
double getComputedAbsErrorBound() const
Definition quant_adaptive_lorenzo_stage.h:126
bool bindDownstreamEncodingOracle(const EncodingOracleDecl &decl) override
Definition quant_adaptive_lorenzo_stage.h:130
size_t estimateScratchBytes(const std::vector< size_t > &input_sizes) const override
size_t serializeHeader(size_t, uint8_t *buf, size_t max_size) const override
Definition quant_adaptive_lorenzo_stage.h:247
uint8_t getInputDataType(size_t input_index) const override
Definition quant_adaptive_lorenzo_stage.h:241
bool isGraphCompatible() const override
Definition quant_adaptive_lorenzo_stage.h:190
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition quant_adaptive_lorenzo_stage.h:264
std::string getName() const override
Definition quant_adaptive_lorenzo_stage.h:175
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition quant_adaptive_lorenzo_stage.h:213
std::vector< std::string > getOutputNames() const override
Definition quant_adaptive_lorenzo_stage.h:179
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
Definition quant_adaptive_lorenzo_stage.h:196
uint8_t getOutputDataType(size_t output_index) const override
Definition quant_adaptive_lorenzo_stage.h:236
std::vector< FusedAuxOutputDecl > getFusedAuxOutputs() const override
Definition quant_adaptive_lorenzo_stage.h:155
void saveState() override
Definition quant_adaptive_lorenzo_stage.h:207
uint16_t getStageTypeId() const override
Definition quant_adaptive_lorenzo_stage.h:232
void setFusedSideOutput(int output_index, size_t bytes) override
Definition quant_adaptive_lorenzo_stage.h:226
size_t getMaxHeaderSize(size_t) const override
Definition quant_adaptive_lorenzo_stage.h:280
Compile-time C++ type -> DataType enum mapping, shared by the fused stages that dispatch on multiple ...
Fused Lorenzo predictor and quantizer stage.
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
@ FUSED_QUANT_ADAPTIVE_LORENZO
AdaptiveLorenzo with the upstream linear Quantizer fused into its forward kernel (FSZ "M1" partial fu...
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:142
@ CompactedElements
runtime count * sizeof(element)
@ FixedBitsPerUnit
ceil(num_units * bits_per_unit / 8)
EncodingOracleKind
Registered exact encoded-size policies used by an upstream adaptive stage for an algorithmic mode dec...
Definition fusion.h:90
Base class interface for all compression stages.
Host-side declaration of a local, exact encoded-size oracle.
Definition fusion.h:104
uint8_t input_data_type
DataType value; 0xFF = unknown.
Definition fusion.h:109
Definition quant_adaptive_lorenzo_stage.h:34
uint8_t coder_block_size
Fixed at 32.
Definition quant_adaptive_lorenzo_stage.h:35
uint8_t eb_mode
ErrorBoundMode cast to uint8_t.
Definition quant_adaptive_lorenzo_stage.h:39
double value_base_f64
NOA/PREL scan result; 0 for ABS.
Definition quant_adaptive_lorenzo_stage.h:43
float user_error_bound
Original config_.error_bound, narrow copy (debug only).
Definition quant_adaptive_lorenzo_stage.h:44
A stage's fusion contract. Stages that can participate in a fused kernel override Stage::getFusionSpe...
Definition fusion.h:51
Backend-neutral GPU type aliases.