FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
adaptive_bitpack_stage.h
Go to the documentation of this file.
1#pragma once
2
11#include "stage/stage.h"
12#include "fzm_format.h"
13#include "backend/types.h"
14#include <cstdint>
15#include <cstring>
16#include <stdexcept>
17#include <string>
18#include <type_traits>
19#include <unordered_map>
20#include <vector>
21
22namespace fz {
23
39static_assert(sizeof(AdaptiveBitpackConfig) <= FZM_STAGE_CONFIG_SIZE,
40 "AdaptiveBitpackConfig must fit in FZM_STAGE_CONFIG_SIZE");
41
74template<typename T>
76 static_assert(std::is_same_v<T, int16_t> || std::is_same_v<T, int32_t>,
77 "AdaptiveBitpackStage: T must be int16_t or int32_t.");
78public:
79 AdaptiveBitpackStage() = default;
80 ~AdaptiveBitpackStage() override;
81
82 // ── Stage control ──────────────────────────────────────────────────────
83 void setInverse(bool inv) override { is_inverse_ = inv; }
84 bool isInverse() const override { return is_inverse_; }
85 // Forward (compress) is graph-capturable: execute() enqueues only
86 // device-side work and the data-dependent compressed-size readback is
87 // deferred to postStreamSync() (run after the launch, outside any capture
88 // window). The inverse path keeps a per-execute layout and is left out of
89 // graph capture, mirroring RZEStage.
90 bool isGraphCompatible() const override { return !is_inverse_; }
91
94 void setBlockSize(uint32_t n) {
95 if (n == 0 || n > 1024)
96 throw std::invalid_argument(
97 "AdaptiveBitpackStage::setBlockSize: n must be in [1, 1024], got "
98 + std::to_string(n));
99 block_size_ = n;
100 }
101 uint32_t getBlockSize() const { return block_size_; }
102
107 FusionSpec getFusionSpec() const override {
108 if (is_inverse_ || (block_size_ != 32u && block_size_ != 64u)) return {};
109 return FusionSpec{FusionAccess::Cooperative, block_size_};
110 }
111
117 FusedOpDecl getFusedOp() const override {
118 if (!getFusionSpec().fusable() || !outlier_selection_) return {};
119 FusedOpDecl d;
120 d.strategy = FusionStrategy::WarpRegister;
121 d.op_name = fused_coder_;
122 d.include_header = "fused/fused_block/warp_fusion.cuh";
123 return d;
124 }
125
131 if (is_inverse_ || block_size_ == 0) return {};
133 d.kind = outlier_selection_
134 ? EncodingOracleKind::AdaptiveFixedRateBitpack
135 : EncodingOracleKind::PlainFixedRateBitpack;
136 d.op_name = outlier_selection_ ? "AdaptiveBitpackCoder" : "PlainBitpackCoder";
137 d.include_header = "fused/fused_block/warp_fusion.cuh";
138 d.input_data_type = static_cast<uint8_t>(getElementDataType());
139 d.unit_elems = block_size_;
140 d.exact = true;
141 d.additive = true;
142 return d;
143 }
144
150 void setFusedCoder(std::string name) { fused_coder_ = std::move(name); }
151 const std::string& getFusedCoder() const { return fused_coder_; }
152
157 void setFusedResult(size_t num_elements, size_t archive_bytes) {
158 num_elements_ = num_elements;
159 actual_output_size_ = archive_bytes;
160 }
161 void setFusedArchiveResult(size_t archive_bytes, size_t orig_bytes) override {
162 setFusedResult(orig_bytes / sizeof(T), archive_bytes);
163 }
164
169 void setOutlierSelection(bool enable) { outlier_selection_ = enable; }
170 bool getOutlierSelection() const { return outlier_selection_; }
171
172 // ── Execution ──────────────────────────────────────────────────────────
174 fz::stream_t stream,
175 MemoryPool* pool,
176 const std::vector<void*>& inputs,
177 const std::vector<void*>& outputs,
178 const std::vector<size_t>& sizes
179 ) override;
180
185 void postStreamSync(fz::stream_t stream) override;
186
187 // ── Metadata ───────────────────────────────────────────────────────────
188 std::string getName() const override { return "AdaptiveBitpack"; }
189 size_t getNumInputs() const override { return 1; }
190 size_t getNumOutputs() const override { return 1; }
191
192 std::vector<size_t> estimateOutputSizes(
193 const std::vector<size_t>& input_sizes
194 ) const override;
195
201 const std::vector<size_t>& input_sizes
202 ) const override;
203
204 std::unordered_map<std::string, size_t>
205 getActualOutputSizesByName() const override {
206 return {{"output", actual_output_size_}};
207 }
208 size_t getActualOutputSize(int index) const override {
209 return (index == 0) ? actual_output_size_ : 0;
210 }
211
212 uint16_t getStageTypeId() const override {
213 return static_cast<uint16_t>(StageType::ADAPTIVE_BITPACK);
214 }
215
216 // Forward: signed codes -> uint8 archive. Inverse: archive -> signed codes.
217 uint8_t getOutputDataType(size_t) const override {
218 return static_cast<uint8_t>(is_inverse_ ? getElementDataType()
219 : DataType::UINT8);
220 }
221 uint8_t getInputDataType(size_t) const override {
222 return static_cast<uint8_t>(is_inverse_ ? DataType::UINT8
223 : getElementDataType());
224 }
225
226 // ── Serialization ──────────────────────────────────────────────────────
227 size_t serializeHeader(size_t, uint8_t* buf, size_t max_size) const override {
228 if (max_size < sizeof(AdaptiveBitpackConfig)) return 0;
230 cfg.data_type = getElementDataType();
231 cfg.outlier_selection = outlier_selection_ ? uint8_t{1} : uint8_t{0};
232 cfg.block_size = block_size_;
233 cfg.num_elements = static_cast<uint64_t>(num_elements_);
234 std::memcpy(buf, &cfg, sizeof(cfg));
235 return sizeof(cfg);
236 }
237 void deserializeHeader(const uint8_t* buf, size_t size) override {
238 if (size < sizeof(AdaptiveBitpackConfig))
239 throw std::runtime_error("AdaptiveBitpackStage: header too small");
241 std::memcpy(&cfg, buf, sizeof(cfg));
242 block_size_ = cfg.block_size ? cfg.block_size : 32u;
243 num_elements_ = static_cast<size_t>(cfg.num_elements);
244 outlier_selection_ = (cfg.outlier_selection != 0);
245 }
246 size_t getMaxHeaderSize(size_t) const override {
247 return sizeof(AdaptiveBitpackConfig);
248 }
249
250 void saveState() override {
251 saved_block_size_ = block_size_;
252 saved_num_elements_ = num_elements_;
253 saved_actual_size_ = actual_output_size_;
254 saved_outlier_select_ = outlier_selection_;
255 }
256 void restoreState() override {
257 block_size_ = saved_block_size_;
258 num_elements_ = saved_num_elements_;
259 actual_output_size_ = saved_actual_size_;
260 outlier_selection_ = saved_outlier_select_;
261 }
262
263 size_t getNumElements() const { return num_elements_; }
264
265private:
266 bool is_inverse_ = false;
267 uint32_t block_size_ = 32;
268 bool outlier_selection_ = false;
269 size_t num_elements_ = 0;
270 size_t actual_output_size_ = 0;
276 std::string fused_coder_ = "AdaptiveBitpackCoder";
277
278 // Forward-path persistent scratch (kept alive across execute() so the
279 // compressed-size readback can be deferred to postStreamSync(), and so no
280 // allocation happens inside a captured graph replay). Grown lazily when a
281 // larger input is seen; freed in the destructor. Pool-managed (persistent).
282 uint32_t* d_cost_ = nullptr;
283 uint32_t* d_offset_ = nullptr;
284 size_t scratch_blocks_ = 0;
285 MemoryPool* scratch_pool_ = nullptr;
286 size_t fwd_num_blocks_ = 0;
287 size_t fwd_meta_region_ = 0;
288
289 uint32_t saved_block_size_ = 32;
290 bool saved_outlier_select_ = false;
291 size_t saved_num_elements_ = 0;
292 size_t saved_actual_size_ = 0;
293
294 static DataType getElementDataType() {
295 if (std::is_same<T, int16_t>::value) return DataType::INT16;
296 return DataType::INT32;
297 }
298};
299
300extern template class AdaptiveBitpackStage<int16_t>;
301extern template class AdaptiveBitpackStage<int32_t>;
302
303} // namespace fz
Definition adaptive_bitpack_stage.h:75
void setFusedArchiveResult(size_t archive_bytes, size_t orig_bytes) override
Definition adaptive_bitpack_stage.h:161
void setBlockSize(uint32_t n)
Definition adaptive_bitpack_stage.h:94
void postStreamSync(fz::stream_t stream) override
void saveState() override
Definition adaptive_bitpack_stage.h:250
size_t serializeHeader(size_t, uint8_t *buf, size_t max_size) const override
Definition adaptive_bitpack_stage.h:227
uint8_t getInputDataType(size_t) const override
Definition adaptive_bitpack_stage.h:221
FusionSpec getFusionSpec() const override
Definition adaptive_bitpack_stage.h:107
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition adaptive_bitpack_stage.h:237
std::string getName() const override
Definition adaptive_bitpack_stage.h:188
uint16_t getStageTypeId() const override
Definition adaptive_bitpack_stage.h:212
size_t getMaxHeaderSize(size_t) const override
Definition adaptive_bitpack_stage.h:246
uint8_t getOutputDataType(size_t) const override
Definition adaptive_bitpack_stage.h:217
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition adaptive_bitpack_stage.h:205
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
EncodingOracleDecl getEncodingOracle() const override
Definition adaptive_bitpack_stage.h:130
size_t getActualOutputSize(int index) const override
Definition adaptive_bitpack_stage.h:208
size_t estimateScratchBytes(const std::vector< size_t > &input_sizes) const override
bool isGraphCompatible() const override
Definition adaptive_bitpack_stage.h:90
void setInverse(bool inv) override
Definition adaptive_bitpack_stage.h:83
void setFusedCoder(std::string name)
Definition adaptive_bitpack_stage.h:150
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
void setOutlierSelection(bool enable)
Definition adaptive_bitpack_stage.h:169
FusedOpDecl getFusedOp() const override
Definition adaptive_bitpack_stage.h:117
void setFusedResult(size_t num_elements, size_t archive_bytes)
Definition adaptive_bitpack_stage.h:157
Definition mempool.h:82
Definition stage.h:31
FZM binary file format definitions — structs, enums, and helpers.
Definition dag.h:24
constexpr size_t FZM_STAGE_CONFIG_SIZE
Per-stage serialized config slot (bytes)
Definition fzm_format.h:65
@ ADAPTIVE_BITPACK
Per-block adaptive fixed-rate bit-plane coder (cuSZp plain mode)
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:139
Base class interface for all compression stages.
Definition adaptive_bitpack_stage.h:28
uint8_t _pad[2]
Must be zero.
Definition adaptive_bitpack_stage.h:31
uint8_t outlier_selection
1 = cuSZp2 per-block plain/outlier selection.
Definition adaptive_bitpack_stage.h:30
uint32_t block_size
Elements per logical block (reset period).
Definition adaptive_bitpack_stage.h:32
DataType data_type
Signed element type (1B): INT16 / INT32.
Definition adaptive_bitpack_stage.h:29
uint64_t num_elements
Original element count (sizes the inverse output).
Definition adaptive_bitpack_stage.h:33
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 contribution to a generated fused kernel — the device-op it maps to, where its source lives...
Definition fusion.h:161
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
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.