FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
clog_stage.h
Go to the documentation of this file.
1#pragma once
2
30#include "stage/stage.h"
31#include "fzm_format.h"
32#include "backend/types.h"
33#include <cstdint>
34#include <cstring>
35#include <stdexcept>
36#include <string>
37#include <unordered_map>
38#include <vector>
39
40namespace fz {
41
59class CLOGStage : public Stage {
60public:
61 CLOGStage()
62 : is_inverse_(false)
63 , chunk_size_(16384)
64 , word_size_(1)
65 , actual_output_size_(0)
66 , cached_orig_bytes_(0)
67 , d_scratch_(nullptr)
68 , d_sizes_dev_(nullptr)
69 , d_clean_dev_(nullptr)
70 , d_dst_off_dev_(nullptr)
71 , scratch_capacity_(0)
72 {}
73
74 ~CLOGStage() override;
75
76 // ── Stage control ──────────────────────────────────────────────────────
77 void setInverse(bool inv) override { is_inverse_ = inv; }
78 bool isInverse() const override { return is_inverse_; }
79
83 bool isGraphCompatible() const override { return !is_inverse_; }
84
85 void setChunkSize(size_t bytes) { chunk_size_ = static_cast<uint32_t>(bytes); }
86 void setWordSize(size_t bytes) { word_size_ = static_cast<uint8_t>(bytes); }
87
88 size_t getChunkSize() const { return chunk_size_; }
89 size_t getRequiredInputAlignment() const override { return chunk_size_; }
90 int getWordSize() const { return static_cast<int>(word_size_); }
91 uint32_t getCachedOrigBytes() const { return cached_orig_bytes_; }
92
93 // ── Fusion (chunk-cooperative coder sink) ────────────────────────────────
94 // Byte-word 16 KB shape only — matches the fused CLOGCoder device op
95 // (d_CLOG<uint8_t, 16384>, identical to word_size==1 execute()).
96 FusionSpec getFusionSpec() const override {
97 if (is_inverse_ || word_size_ != 1 || chunk_size_ != 16384u) return {};
98 return FusionSpec{FusionAccess::Cooperative, chunk_size_};
99 }
100 FusedOpDecl getFusedOp() const override {
101 if (!getFusionSpec().fusable()) return {};
102 return FusedOpDecl{FusionStrategy::ChunkCooperative, "CLOGCoder",
103 "fused/chunk_fusion/chunk_fusion.cuh", {}};
104 }
105 void setFusedResult(size_t archive_bytes, size_t orig_bytes) {
106 actual_output_size_ = archive_bytes;
107 cached_orig_bytes_ = static_cast<uint32_t>(orig_bytes);
108 tail_readback_pending_ = false;
109 }
110 void setFusedArchiveResult(size_t archive_bytes, size_t orig_bytes) override {
111 setFusedResult(archive_bytes, orig_bytes);
112 }
113
114 // ── Execution ──────────────────────────────────────────────────────────
116 cudaStream_t stream,
117 MemoryPool* pool,
118 const std::vector<void*>& inputs,
119 const std::vector<void*>& outputs,
120 const std::vector<size_t>& sizes
121 ) override;
122 void postStreamSync(cudaStream_t stream) override;
123
124 // ── Metadata ───────────────────────────────────────────────────────────
125 std::string getName() const override { return "CLOG"; }
126 size_t getNumInputs() const override { return 1; }
127 size_t getNumOutputs() const override { return 1; }
128
129 std::vector<size_t> estimateOutputSizes(
130 const std::vector<size_t>& input_sizes
131 ) const override {
132 if (is_inverse_) {
133 if (cached_orig_bytes_ > 0)
134 return {static_cast<size_t>(cached_orig_bytes_)};
135 return {input_sizes.empty() ? 0 : input_sizes[0]};
136 }
137 // Forward: worst case = original data + stream header.
138 const size_t n_bytes = input_sizes.empty() ? 0 : input_sizes[0];
139 const size_t n_chunks = (n_bytes + chunk_size_ - 1) / chunk_size_;
140 const size_t hdr = 4 + 4 + 4 * n_chunks;
141 // postStreamSync()/getActualOutputSizesByName() always round the final
142 // size up to a 4-byte boundary and zero-fill the pad, even when the
143 // real total isn't already aligned (e.g. a partial final chunk stored
144 // raw at a byte count that isn't a multiple of 4) -- reserve that pad
145 // here too, or the caller's allocation is up to 3 bytes short and the
146 // memset in postStreamSync writes out of bounds.
147 const size_t worst = n_bytes + hdr;
148 return {(worst + 3) & ~size_t(3)};
149 }
150
151 std::unordered_map<std::string, size_t>
153 size_t getActualOutputSize(int index) const override;
154
164 const std::vector<size_t>& input_sizes
165 ) const override {
166 if (is_inverse_ || input_sizes.empty()) return 0;
167 const size_t in_bytes = input_sizes[0];
168 const size_t n_chunks = (in_bytes + chunk_size_ - 1) / chunk_size_;
169 return n_chunks * (static_cast<size_t>(chunk_size_) + 3 * sizeof(uint32_t));
170 }
171
172 uint16_t getStageTypeId() const override {
173 return static_cast<uint16_t>(StageType::CLOG);
174 }
175
176 uint8_t getOutputDataType(size_t) const override {
177 return static_cast<uint8_t>(DataType::UINT8);
178 }
179
180 // ── Serialization ──────────────────────────────────────────────────────
182 size_t output_index, uint8_t* buf, size_t max_size
183 ) const override {
184 (void)output_index;
185 if (max_size < 9) return 0;
186 std::memcpy(buf, &chunk_size_, sizeof(uint32_t));
187 buf[4] = word_size_;
188 std::memcpy(buf + 5, &cached_orig_bytes_, sizeof(uint32_t));
189 return 9;
190 }
191
192 void deserializeHeader(const uint8_t* buf, size_t size) override {
193 if (size >= 4) std::memcpy(&chunk_size_, buf, sizeof(uint32_t));
194 if (size >= 5) word_size_ = buf[4];
195 if (size >= 9) std::memcpy(&cached_orig_bytes_, buf + 5, sizeof(uint32_t));
196 }
197
198 size_t getMaxHeaderSize(size_t) const override { return 9; }
199
200 void saveState() override {
201 saved_chunk_size_ = chunk_size_;
202 saved_word_size_ = word_size_;
203 saved_cached_orig_bytes_ = cached_orig_bytes_;
204 }
205
206 void restoreState() override {
207 chunk_size_ = saved_chunk_size_;
208 word_size_ = saved_word_size_;
209 cached_orig_bytes_ = saved_cached_orig_bytes_;
210 }
211
212private:
213 bool is_inverse_;
214 uint32_t chunk_size_;
215 uint32_t saved_chunk_size_ = 0;
216 uint8_t word_size_;
217 uint8_t saved_word_size_ = 0;
218 size_t actual_output_size_;
219 uint32_t cached_orig_bytes_ = 0;
220 uint32_t saved_cached_orig_bytes_ = 0;
221
222 // ── Persistent forward scratch buffers ───────────────────────────────────
223 uint8_t* d_scratch_;
224 uint32_t* d_sizes_dev_;
225 uint32_t* d_clean_dev_;
226 uint32_t* d_dst_off_dev_;
227 mutable bool tail_readback_pending_ = false;
228 mutable cudaStream_t tail_readback_stream_ = nullptr;
229 mutable uint32_t tail_last_index_ = 0;
230 mutable uint8_t* tail_output_ptr_ = nullptr;
231 size_t scratch_capacity_;
232 MemoryPool* scratch_pool_owner_ = nullptr;
233 bool scratch_from_pool_ = false;
234};
235
236} // namespace fz
Definition clog_stage.h:59
bool isGraphCompatible() const override
Definition clog_stage.h:83
size_t serializeHeader(size_t output_index, uint8_t *buf, size_t max_size) const override
Definition clog_stage.h:181
void postStreamSync(cudaStream_t stream) override
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition clog_stage.h:192
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
Definition clog_stage.h:129
uint16_t getStageTypeId() const override
Definition clog_stage.h:172
size_t getMaxHeaderSize(size_t) const override
Definition clog_stage.h:198
void setInverse(bool inv) override
Definition clog_stage.h:77
size_t getActualOutputSize(int index) const override
FusionSpec getFusionSpec() const override
Definition clog_stage.h:96
size_t getRequiredInputAlignment() const override
Definition clog_stage.h:89
uint8_t getOutputDataType(size_t) const override
Definition clog_stage.h:176
FusedOpDecl getFusedOp() const override
Definition clog_stage.h:100
size_t estimateScratchBytes(const std::vector< size_t > &input_sizes) const override
Definition clog_stage.h:163
std::string getName() const override
Definition clog_stage.h:125
void execute(cudaStream_t stream, MemoryPool *pool, const std::vector< void * > &inputs, const std::vector< void * > &outputs, const std::vector< size_t > &sizes) override
void setFusedArchiveResult(size_t archive_bytes, size_t orig_bytes) override
Definition clog_stage.h:110
void saveState() override
Definition clog_stage.h:200
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition mempool.h:82
Definition stage.h:31
FZM binary file format definitions — structs, enums, and helpers.
Definition dag.h:24
@ CLOG
Per-subchunk leading-zero compression and bit packing (LC framework component)
Base class interface for all compression stages.
A stage's contribution to a generated fused kernel — the device-op it maps to, where its source lives...
Definition fusion.h:161
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.