18#include <unordered_map>
39 "AdaptiveLorenzoConfig must fit in FZM_STAGE_CONFIG_SIZE");
96 static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
97 "AdaptiveLorenzoStage requires a signed integer type");
104 uint32_t coder_block_size = 32;
109 uint32_t blocks_per_tile = 8;
110 bool enable_order2 =
true;
111 bool enable_centering =
true;
119 bool isInverse()
const override {
return is_inverse_; }
121 uint32_t getTileSize()
const {
122 return config_.coder_block_size * config_.blocks_per_tile;
129 if (!decl.valid() || !decl.additive ||
130 (decl.kind != EncodingOracleKind::PlainFixedRateBitpack &&
131 decl.kind != EncodingOracleKind::AdaptiveFixedRateBitpack) ||
133 decl.unit_elems != config_.coder_block_size) {
136 bound_oracle_ = decl;
137 has_bound_oracle_ =
true;
141 bool hasBoundEncodingOracle()
const {
return has_bound_oracle_; }
143 return has_bound_oracle_ ? bound_oracle_.kind
144 : EncodingOracleKind::PlainFixedRateBitpack;
148 if (is_inverse_ || !has_bound_oracle_)
return {};
149 return FusionSpec{FusionAccess::TileAdaptive, getTileSize(),
150 config_.coder_block_size};
157 static_cast<uint8_t
>(DataType::UINT8), getTileSize(),
160 static_cast<uint8_t
>(getElementDataType()), getTileSize(),
168 const std::vector<void*>& inputs,
169 const std::vector<void*>& outputs,
170 const std::vector<size_t>& sizes
173 std::string
getName()
const override {
return "AdaptiveLorenzo"; }
174 size_t getNumInputs()
const override {
return is_inverse_ ? 3 : 1; }
175 size_t getNumOutputs()
const override {
return is_inverse_ ? 1 : 3; }
178 return {
"output",
"modes",
"means"};
194 const std::vector<size_t>& input_sizes
198 const std::vector<size_t>& input_sizes
200 if (input_sizes.empty())
return {0, 0, 0};
201 if (is_inverse_)
return {input_sizes[0]};
202 const size_t n = input_sizes[0] /
sizeof(T);
203 const size_t tiles = numTiles(n);
206 return {input_sizes[0], (tiles + 3) / 4, tiles *
sizeof(T)};
209 void saveState()
override { saved_output_sizes_ = actual_output_sizes_; }
210 void restoreState()
override {
211 if (!saved_output_sizes_.empty()) actual_output_sizes_ = saved_output_sizes_;
214 std::unordered_map<std::string, size_t>
217 std::unordered_map<std::string, size_t> r;
218 for (
size_t i = 0; i < names.size() && i < actual_output_sizes_.size(); ++i)
219 r[names[i]] = actual_output_sizes_[i];
224 return (index >= 0 && index <
static_cast<int>(actual_output_sizes_.size()))
225 ? actual_output_sizes_[index] : 0;
229 if (actual_output_sizes_.size() < 3) actual_output_sizes_.resize(3, 0);
230 if (output_index == 1 || output_index == 2)
231 actual_output_sizes_[
static_cast<size_t>(output_index)] = bytes;
240 return static_cast<uint8_t
>(output_index == 1 ? DataType::UINT8
241 : getElementDataType());
244 return static_cast<uint8_t
>(input_index == 1 ? DataType::UINT8
245 : getElementDataType());
250 throw std::runtime_error(
"AdaptiveLorenzoStage: header buffer too small");
257 cfg.
num_elements =
static_cast<uint32_t
>(num_elements_);
258 std::memcpy(buf, &cfg,
sizeof(cfg));
264 throw std::runtime_error(
"AdaptiveLorenzoStage: header too small");
266 std::memcpy(&cfg, buf,
sizeof(cfg));
282 bool has_bound_oracle_ =
false;
283 bool is_inverse_ =
false;
284 size_t num_elements_ = 0;
285 std::vector<size_t> actual_output_sizes_{0, 0, 0};
286 std::vector<size_t> saved_output_sizes_;
290 uint8_t* d_modes_dense_ =
nullptr;
291 T* d_means_dense_ =
nullptr;
292 uint32_t* d_flags_ =
nullptr;
293 uint32_t* d_offsets_ =
nullptr;
294 size_t scratch_tiles_ = 0;
295 MemoryPool* scratch_pool_ =
nullptr;
296 size_t pending_tiles_ = 0;
298 size_t ensureScratch(
size_t num_tiles, MemoryPool* pool, fz::stream_t stream);
299 void releaseScratch();
301 size_t numTiles(
size_t n)
const {
302 const size_t t = getTileSize();
303 return (n + t - 1) / t;
306 void validate()
const {
307 if (config_.coder_block_size != 32)
308 throw std::invalid_argument(
309 "AdaptiveLorenzoStage: coder_block_size must be 32 (the cost model "
310 "and the per-block warp reduction both assume a 32-element block)");
311 if (config_.blocks_per_tile < 1 || config_.blocks_per_tile > 32)
312 throw std::invalid_argument(
313 "AdaptiveLorenzoStage: blocks_per_tile must be in [1, 32] so the "
314 "tile fits one CUDA block, got "
315 + std::to_string(config_.blocks_per_tile));
318 static DataType getElementDataType() {
319 if (std::is_same<T, int8_t>::value)
return DataType::INT8;
320 if (std::is_same<T, int16_t>::value)
return DataType::INT16;
321 if (std::is_same<T, int32_t>::value)
return DataType::INT32;
322 if (std::is_same<T, int64_t>::value)
return DataType::INT64;
323 return DataType::INT32;
327extern template class AdaptiveLorenzoStage<int16_t>;
328extern template class AdaptiveLorenzoStage<int32_t>;
333 const T* d_input, T* d_residuals, uint8_t* d_modes, T* d_means,
334 uint32_t* d_flags,
size_t n, uint32_t tile_size,
bool enable_order2,
340 const T* d_residuals,
const uint8_t* d_modes,
const T* d_means, T* d_output,
341 size_t n, uint32_t tile_size, fz::stream_t stream);
Definition adaptive_lorenzo_stage.h:95
uint16_t getStageTypeId() const override
Definition adaptive_lorenzo_stage.h:234
uint8_t getInputDataType(size_t input_index) const override
Definition adaptive_lorenzo_stage.h:243
size_t estimateScratchBytes(const std::vector< size_t > &input_sizes) const override
Defined in the .cu — sizing the CUB scan temp needs a CUDA translation unit.
size_t serializeHeader(size_t, uint8_t *buf, size_t max_size) const override
Definition adaptive_lorenzo_stage.h:248
size_t getMaxHeaderSize(size_t) const override
Definition adaptive_lorenzo_stage.h:275
bool isGraphCompatible() const override
Definition adaptive_lorenzo_stage.h:190
std::vector< FusedAuxOutputDecl > getFusedAuxOutputs() const override
Definition adaptive_lorenzo_stage.h:153
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition adaptive_lorenzo_stage.h:215
bool bindDownstreamEncodingOracle(const EncodingOracleDecl &decl) override
Definition adaptive_lorenzo_stage.h:128
void setInverse(bool inv) override
Definition adaptive_lorenzo_stage.h:118
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition adaptive_lorenzo_stage.h:262
std::string getName() const override
Definition adaptive_lorenzo_stage.h:173
uint8_t getOutputDataType(size_t output_index) const override
Definition adaptive_lorenzo_stage.h:238
FusionSpec getFusionSpec() const override
Definition adaptive_lorenzo_stage.h:147
std::vector< std::string > getOutputNames() const override
Definition adaptive_lorenzo_stage.h:177
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 getActualOutputSize(int index) const override
Definition adaptive_lorenzo_stage.h:223
void postStreamSync(fz::stream_t stream) override
void saveState() override
Definition adaptive_lorenzo_stage.h:209
void setFusedSideOutput(int output_index, size_t bytes) override
Definition adaptive_lorenzo_stage.h:228
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
Definition adaptive_lorenzo_stage.h:197
constexpr size_t FZM_STAGE_CONFIG_SIZE
Per-stage serialized config slot (bytes)
Definition fzm_format.h:65
@ ADAPTIVE_LORENZO
Per-tile adaptive multi-order Lorenzo + centering (FSZ prediction stage)
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:139
@ CompactedElements
runtime count * sizeof(element)
@ FixedBitsPerUnit
ceil(num_units * bits_per_unit / 8)
void launchAdaptiveLorenzoForward(const T *d_input, T *d_residuals, uint8_t *d_modes, T *d_means, uint32_t *d_flags, size_t n, uint32_t tile_size, bool enable_order2, bool enable_centering, EncodingOracleKind oracle_kind, fz::stream_t stream)
Forward: select the best variant per tile and emit its residuals.
EncodingOracleKind
Registered exact encoded-size policies used by an upstream adaptive stage for an algorithmic mode dec...
Definition fusion.h:90
void launchAdaptiveLorenzoInverse(const T *d_residuals, const uint8_t *d_modes, const T *d_means, T *d_output, size_t n, uint32_t tile_size, fz::stream_t stream)
Inverse: replay each tile's recorded variant.
Base class interface for all compression stages.
Serialized config stored in FZMBufferEntry.stage_config.
Definition adaptive_lorenzo_stage.h:24
uint8_t reserved[3]
Must be zero.
Definition adaptive_lorenzo_stage.h:30
uint8_t enable_order2
1 if LZ2 is a candidate variant.
Definition adaptive_lorenzo_stage.h:28
uint8_t blocks_per_tile
Coder blocks per adaptation tile.
Definition adaptive_lorenzo_stage.h:27
DataType data_type
Signed integer element type (1B).
Definition adaptive_lorenzo_stage.h:25
uint8_t coder_block_size
Downstream coder's block size (fixed at 32).
Definition adaptive_lorenzo_stage.h:26
uint8_t enable_centering
1 if centering is a candidate variant.
Definition adaptive_lorenzo_stage.h:29
uint32_t num_elements
Element count (for tile-count recovery).
Definition adaptive_lorenzo_stage.h:31
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
A stage's fusion contract. Stages that can participate in a fused kernel override Stage::getFusionSpe...
Definition fusion.h:52
Backend-neutral GPU type aliases.