30#include "coders/huffman/phf/hf.h"
39#include <unordered_map>
44namespace phf {
template<
typename E>
struct Buf; }
122 std::is_same_v<T, uint8_t> ||
123 std::is_same_v<T, uint16_t> ||
124 std::is_same_v<T, uint32_t>,
125 "HuffmanStage: T must be uint8_t, uint16_t, or uint32_t.");
171 constexpr uint32_t kMul = (4u /
sizeof(T)) ? (4u /
sizeof(T)) : 1u;
172 uint32_t rounded = ((bklen + kMul - 1u) / kMul) * kMul;
178 if (rounded > 0xFFFFu)
179 throw std::invalid_argument(
180 "HuffmanStage::setBklen: bklen (after rounding, " + std::to_string(rounded) +
181 ") exceeds 65535 — bklen_ is a uint16_t end to end (serialized header and "
182 "histogram kernel API), so the full symbol range of a 16+ bit type cannot be "
183 "histogrammed in one pass. Reduce the upstream quant_radius/code range, or "
184 "split the input across multiple Huffman stages.");
187 uint32_t getBklen()
const {
return bklen_; }
267 bool getValidateSymbolRange()
const {
return validate_symbol_range_; }
289 uint8_t getAdaptiveFloorShift()
const {
return adaptive_floor_shift_; }
312 if (adaptive_fallback_)
return {
"huffman_adaptive_fallback"};
334 float getRefitThreshold()
const {
return refit_threshold_; }
355 uint32_t getRefitInterval()
const {
return refit_interval_; }
375 bool isInverse()
const override {
return is_inverse_; }
405 const std::vector<void*>& inputs,
406 const std::vector<void*>& outputs,
407 const std::vector<size_t>& sizes
411 std::string
getName()
const override {
return "Huffman"; }
412 size_t getNumInputs()
const override {
return 1; }
413 size_t getNumOutputs()
const override {
return 1; }
416 const std::vector<size_t>& input_sizes
418 if (input_sizes.empty())
return {0};
420 const size_t n = input_sizes[0] /
sizeof(T);
421 if (n == 0)
return {0};
422 const size_t sublen = capi_phf_coarse_tune_sublen(n);
423 const size_t pardeg = (n - 1) / sublen + 1;
424 constexpr size_t kMaxCodeBits = 27;
425 constexpr size_t kCellBits = 32;
426 const size_t cells_per_partition =
427 (sublen * kMaxCodeBits + kCellBits - 1) / kCellBits;
428 const size_t bitstream_bytes = pardeg * cells_per_partition *
sizeof(uint32_t);
429 const size_t reverse_book_bytes =
430 phf_reverse_book_bytes(
static_cast<uint16_t
>(bklen_), 4,
sizeof(T));
431 return {PHFHEADER_FORCED_ALIGN + reverse_book_bytes
432 + 2 * pardeg *
sizeof(PHF_METADATA) + bitstream_bytes};
435 return {original_len_ *
sizeof(T)};
438 std::unordered_map<std::string, size_t>
440 return {{
"output", actual_output_size_}};
444 return (index == 0) ? actual_output_size_ : 0;
449 return static_cast<uint16_t
>(StageType::HUFFMAN);
462 size_t , uint8_t* buf,
size_t max_size
464 if (max_size < 11)
return 0;
465 buf[0] =
static_cast<uint8_t
>(dataTypeOf<T>());
466 uint16_t bk =
static_cast<uint16_t
>(bklen_);
467 std::memcpy(buf + 1, &bk,
sizeof(uint16_t));
468 std::memcpy(buf + 3, &original_len_,
sizeof(uint64_t));
475 std::memcpy(&bk, buf + 1,
sizeof(uint16_t));
486 if ((
sizeof(T) *
static_cast<size_t>(bk)) % 4u != 0)
487 throw std::runtime_error(
488 "HuffmanStage: archive declares bklen=" + std::to_string(bk) +
489 " with a " + std::to_string(
sizeof(T)) +
"-byte symbol, which puts "
490 "the bitstream at a non-4-byte offset. Such archives were written "
491 "by a build predating the alignment fix and cannot be decoded "
492 "correctly — the stream itself is malformed, not just this reader.");
496 std::memcpy(&original_len_, buf + 3,
sizeof(uint64_t));
502 saved_bklen_ = bklen_;
503 saved_original_len_ = original_len_;
504 saved_output_size_ = actual_output_size_;
507 void restoreState()
override {
508 bklen_ = saved_bklen_;
509 original_len_ = saved_original_len_;
510 actual_output_size_ = saved_output_size_;
514 bool is_inverse_ =
false;
515 uint32_t bklen_ = defaultBklen();
520 std::vector<uint32_t> fixed_freq_;
522 HuffmanBookSpec book_spec_ {};
523 bool has_book_spec_ =
false;
524 uint8_t adaptive_floor_shift_ = 24;
525 uint8_t adaptive_shift_used_ = 24;
530 bool adaptive_fallback_ =
false;
533 float refit_threshold_ = 1.2f;
534 bool validate_symbol_range_ =
true;
535 uint32_t refit_interval_ = 0;
536 uint32_t calls_since_fit_ = 0;
537 double fit_bits_per_sym_ = 0.0;
538 bool just_fitted_ =
false;
539 uint32_t refit_count_ = 0;
542 bool fixed_book_resident_ =
false;
544 uint64_t original_len_ = 0;
545 size_t actual_output_size_ = 0;
546 size_t cap_inlen_ = 0;
547 uint32_t last_bklen_ = 0;
550 int hist_grid_dim_ = 0;
551 int hist_block_dim_ = 0;
552 int hist_shmem_use_ = 0;
553 int hist_r_per_block_ = 0;
556 std::unique_ptr<phf::Buf<T>> buf_;
557 phf_header header_ {};
558 uint8_t* pending_device_output_ =
nullptr;
559 bool pending_device_readback_ =
false;
560 size_t pending_device_inlen_ = 0;
561 bool is_terminal_output_ =
true;
566 MemoryPool* pool_ =
nullptr;
569 uint32_t saved_bklen_ = defaultBklen();
570 uint64_t saved_original_len_ = 0;
571 size_t saved_output_size_ = 0;
573 static constexpr uint32_t defaultBklen() {
574 if constexpr (std::is_same_v<T, uint8_t>)
return 256;
579 static constexpr DataType dataTypeOf() {
580 if constexpr (std::is_same_v<U, uint8_t>)
return DataType::UINT8;
581 if constexpr (std::is_same_v<U, uint16_t>)
return DataType::UINT16;
582 return DataType::UINT32;
589 void initBuf(
size_t inlen, MemoryPool* pool);
593 void buildFixedBook(fz::stream_t stream);
597 void buildAdaptiveBook(
const uint32_t* h_hist, fz::stream_t stream);
601 void buildDeviceBook(fz::stream_t stream, MemoryPool* pool,
602 size_t expected_symbols, uint32_t source_mode);
606 void updateAdaptiveRate(
size_t inlen,
size_t total_nbit);
609 int findUnusableCode(
const uint32_t* freq)
const;
612extern template class HuffmanStage<uint8_t>;
613extern template class HuffmanStage<uint16_t>;
614extern template class HuffmanStage<uint32_t>;
Definition huffman_stage.h:119
size_t estimateDeviceFootprintBytes(size_t inlen) const override
void setRefitThreshold(float ratio)
Definition huffman_stage.h:333
size_t getMaxHeaderSize(size_t) const override
Definition huffman_stage.h:499
size_t serializeHeader(size_t, uint8_t *buf, size_t max_size) const override
Definition huffman_stage.h:461
uint16_t getStageTypeId() const override
Definition huffman_stage.h:448
bool isGraphCompatible() const override
Definition huffman_stage.h:377
double getFitBitsPerSymbol() const
Definition huffman_stage.h:365
std::vector< std::string > getRunNotes() const override
Definition huffman_stage.h:311
void onFinalize(size_t estimated_inlen, MemoryPool *pool) override
size_t getActualOutputSize(int index) const override
Definition huffman_stage.h:443
uint32_t getRefitCount() const
Definition huffman_stage.h:360
void saveState() override
Definition huffman_stage.h:501
bool getAdaptiveFallbackUsed() const
Definition huffman_stage.h:306
bool hasBookSpec() const
Definition huffman_stage.h:370
uint8_t getAdaptiveFloorShiftUsed() const
Definition huffman_stage.h:293
void setInverse(bool inv) override
Definition huffman_stage.h:374
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
Definition huffman_stage.h:415
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition huffman_stage.h:472
void setFixedBookFromFreq(const uint32_t *h_freq, uint32_t n)
void setAdaptiveFloorShift(uint8_t shift)
Definition huffman_stage.h:288
size_t estimatePinnedFootprintBytes(size_t inlen) const override
std::string getName() const override
Definition huffman_stage.h:411
const std::vector< uint32_t > & getFixedBookFreq() const
Frequency table backing the fixed codebook; empty when none has been set.
Definition huffman_stage.h:270
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 setBookSource(HuffmanBookSource src)
Definition huffman_stage.h:213
void setExecutionMode(HuffmanExecutionMode mode)
Definition huffman_stage.h:197
void setTerminalOutput(bool terminal) override
Definition huffman_stage.h:382
uint8_t getOutputDataType(size_t) const override
Definition huffman_stage.h:453
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition huffman_stage.h:439
void setRefitInterval(uint32_t n)
Definition huffman_stage.h:354
void setFixedBookFromModel(const HuffmanBookSpec &spec)
void postStreamSync(fz::stream_t stream) override
void setBklen(uint32_t bklen)
Definition huffman_stage.h:170
uint8_t getInputDataType(size_t) const override
Definition huffman_stage.h:456
void setValidateSymbolRange(bool on)
Definition huffman_stage.h:266
HuffmanBookSource
Definition huffman_stage.h:68
@ Adaptive
Histogram the first call only, then reuse that codebook forever.
@ PerBlock
Histogram + build a fresh codebook on every forward call (default).
@ Fixed
Build one codebook up front and reuse it for every forward call.
HuffmanBookModel
Definition huffman_stage.h:75
@ Laplace
exp(-|i-center|/scale)
@ GeneralizedNormal
exp(-(|i-center|/scale)^shape)
@ Uniform
flat; every symbol equally likely
@ Gaussian
exp(-((i-center)/scale)^2 / 2)
HuffmanExecutionMode
Definition huffman_stage.h:49
@ HostCoordinated
cuSZ coarse path with a host partition-prefix scan (default).
@ DeviceResident
Device scan/header assembly; book construction follows the selected source.
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:139
@ UNKNOWN
Byte-transparent stages: skip type checking at finalize()
Base class interface for all compression stages.
Definition huffman_stage.h:90
double shape
Exponent for GeneralizedNormal only (2.0 == Gaussian, 1.0 == Laplace).
Definition huffman_stage.h:99
double scale
Definition huffman_stage.h:97
double center
Definition huffman_stage.h:94
Backend-neutral GPU type aliases.