FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
lorenzo_stage.h
Go to the documentation of this file.
1#pragma once
2
8#include "stage/stage.h"
9#include "fzm_format.h"
10#include "backend/types.h"
11#include <algorithm>
12#include <array>
13#include <cstdint>
14#include <cstring>
15#include <stdexcept>
16#include <string>
17#include <type_traits>
18#include <unordered_map>
19#include <vector>
20
21namespace fz {
22
30 uint8_t ndim;
31 uint8_t centering;
32 uint8_t order;
33 uint32_t dim_x;
34 uint32_t dim_y;
35 uint32_t dim_z;
36 uint32_t block_size;
37
39 : data_type(DataType::INT32), ndim(1), centering(0), order(1),
40 dim_x(0), dim_y(1), dim_z(1), block_size(0) {}
41};
42static_assert(sizeof(LorenzoConfig) <= FZM_STAGE_CONFIG_SIZE,
43 "LorenzoConfig must fit in FZM_STAGE_CONFIG_SIZE");
44
53template<typename T>
54class LorenzoStage : public Stage {
55 static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
56 "LorenzoStage requires a signed integer type");
57public:
58 LorenzoStage() = default;
59
68 explicit LorenzoStage(uint32_t block_size, bool centering = false,
69 uint8_t order = 1)
70 : block_size_(block_size), centering_(centering), order_(order) {
71 if (block_size > 1024)
72 throw std::invalid_argument(
73 "LorenzoStage: block_size must be in [0, 1024], got "
74 + std::to_string(block_size));
75 if (centering && block_size == 0)
76 throw std::invalid_argument(
77 "LorenzoStage: centering requires block_size > 0");
78 if (order != 1 && order != 2)
79 throw std::invalid_argument(
80 "LorenzoStage: order must be 1 or 2, got " + std::to_string(order));
81 if (order == 2 && block_size == 0)
82 throw std::invalid_argument(
83 "LorenzoStage: order 2 requires block_size > 0");
84 }
85
86 void setInverse(bool inv) override { is_inverse_ = inv; }
87 bool isInverse() const override { return is_inverse_; }
88
89 void setDims(const std::array<size_t, 3>& dims) override { dims_ = dims; }
90 void setDims(size_t x, size_t y = 1, size_t z = 1) { dims_ = {x, y, z}; }
91 std::array<size_t, 3> getDims() const { return dims_; }
92
105 void setBlockSize(uint32_t n) {
106 if (n > 1024)
107 throw std::invalid_argument(
108 "LorenzoStage::setBlockSize: n must be in [0, 1024], got "
109 + std::to_string(n));
110 block_size_ = n;
111 }
112 uint32_t getBlockSize() const { return block_size_; }
113
141 void setCentering(bool enable) { centering_ = enable; }
142 bool getCentering() const { return centering_; }
143
161 void setOrder(uint8_t k) {
162 if (k != 1 && k != 2)
163 throw std::invalid_argument(
164 "LorenzoStage::setOrder: order must be 1 or 2, got " + std::to_string(k));
165 order_ = k;
166 }
167 uint8_t getOrder() const { return order_; }
168
169 int ndim() const {
170 if (dims_[2] > 1) return 3;
171 if (dims_[1] > 1) return 2;
172 return 1;
173 }
174
176 fz::stream_t stream,
177 MemoryPool* pool,
178 const std::vector<void*>& inputs,
179 const std::vector<void*>& outputs,
180 const std::vector<size_t>& sizes
181 ) override;
182
183 std::string getName() const override { return "Lorenzo"; }
184
186 size_t getNumInputs() const override {
187 return (is_inverse_ && centeringActive()) ? 2 : 1;
188 }
189 size_t getNumOutputs() const override {
190 return (!is_inverse_ && centeringActive()) ? 2 : 1;
191 }
192
193 std::vector<std::string> getOutputNames() const override {
194 if (centeringActive()) return {"output", "means"};
195 return {"output"};
196 }
197
198 std::vector<size_t> estimateOutputSizes(
199 const std::vector<size_t>& input_sizes
200 ) const override {
201 const size_t in = input_sizes.empty() ? 0 : input_sizes[0];
202 if (!centeringActive()) return {in};
203 return {in, numBlocks(in / sizeof(T)) * sizeof(T)};
204 }
205
206 std::unordered_map<std::string, size_t>
207 getActualOutputSizesByName() const override {
208 if (centeringActive())
209 return {{"output", actual_output_size_}, {"means", actual_means_size_}};
210 return {{"output", actual_output_size_}};
211 }
212
213 size_t getActualOutputSize(int index) const override {
214 if (index == 0) return actual_output_size_;
215 if (index == 1 && centeringActive()) return actual_means_size_;
216 return 0;
217 }
218
219 uint16_t getStageTypeId() const override {
220 return static_cast<uint16_t>(StageType::LORENZO);
221 }
222
223 uint8_t getOutputDataType(size_t /*output_index*/) const override {
224 return static_cast<uint8_t>(getElementDataType());
225 }
226
227 uint8_t getInputDataType(size_t /*input_index*/) const override {
228 return static_cast<uint8_t>(getElementDataType());
229 }
230
231 size_t serializeHeader(size_t /*output_index*/, uint8_t* buf, size_t max_size) const override {
232 if (max_size < sizeof(LorenzoConfig))
233 throw std::runtime_error("LorenzoStage: header buffer too small");
234 LorenzoConfig cfg;
235 cfg.data_type = getElementDataType();
236 cfg.ndim = static_cast<uint8_t>(ndim());
237 cfg.dim_x = static_cast<uint32_t>(dims_[0]);
238 cfg.dim_y = static_cast<uint32_t>(dims_[1]);
239 cfg.dim_z = static_cast<uint32_t>(dims_[2]);
240 cfg.block_size = block_size_;
241 cfg.centering = centeringActive() ? 1u : 0u;
242 cfg.order = order_;
243 std::memcpy(buf, &cfg, sizeof(LorenzoConfig));
244 return sizeof(LorenzoConfig);
245 }
246
247 void deserializeHeader(const uint8_t* buf, size_t size) override {
248 // Accept legacy 16-byte headers (no block_size field).
249 constexpr size_t kMinSize = 16;
250 if (size < kMinSize)
251 throw std::runtime_error("LorenzoStage: header too small");
252 LorenzoConfig cfg; // default-constructed: block_size = 0
253 std::memcpy(&cfg, buf, std::min(size, sizeof(LorenzoConfig)));
254 int eff_ndim = (cfg.ndim == 0) ? 1 : static_cast<int>(cfg.ndim);
255 dims_[0] = cfg.dim_x;
256 dims_[1] = (eff_ndim >= 2) ? cfg.dim_y : 1;
257 dims_[2] = (eff_ndim >= 3) ? cfg.dim_z : 1;
258 block_size_ = (size >= sizeof(LorenzoConfig)) ? cfg.block_size : 0;
259 // `centering` occupies a byte that legacy writers zeroed as `reserved`,
260 // so old archives decode as centering-off without a version bump.
261 centering_ = (cfg.centering != 0);
262 // `order` reuses a byte legacy writers zeroed as `reserved`; 0 reads as
263 // first order, so pre-LZ2 archives decode unchanged.
264 order_ = (cfg.order == 2) ? 2u : 1u;
265 }
266
267 size_t getMaxHeaderSize(size_t /*output_index*/) const override {
268 return sizeof(LorenzoConfig);
269 }
270
271private:
272 bool is_inverse_ = false;
273 size_t actual_output_size_ = 0;
274 size_t actual_means_size_ = 0;
275 std::array<size_t, 3> dims_ = {0, 1, 1};
276 uint32_t block_size_ = 0;
277 bool centering_ = false;
278 uint8_t order_ = 1;
279
283 bool centeringActive() const { return centering_ && block_size_ > 0; }
284
286 size_t numBlocks(size_t n) const {
287 return (block_size_ == 0) ? 0 : (n + block_size_ - 1) / block_size_;
288 }
289
290 static DataType getElementDataType() {
291 if (std::is_same<T, int8_t>::value) return DataType::INT8;
292 if (std::is_same<T, int16_t>::value) return DataType::INT16;
293 if (std::is_same<T, int32_t>::value) return DataType::INT32;
294 if (std::is_same<T, int64_t>::value) return DataType::INT64;
295 return DataType::INT32;
296 }
297};
298
299extern template class LorenzoStage<int8_t>;
300extern template class LorenzoStage<int16_t>;
301extern template class LorenzoStage<int32_t>;
302extern template class LorenzoStage<int64_t>;
303
304// Kernel launcher declarations — defined in lorenzo_stage.cu.
305
306template<typename T>
307void launchLorenzoDeltaKernel1D(
308 const T* d_input, T* d_output, size_t n, fz::stream_t stream,
309 unsigned block_threads = 256);
310
311template<typename T>
312void launchLorenzoPrefixSumKernel1D(
313 const T* d_input, T* d_output, size_t n, fz::stream_t stream,
314 unsigned block_threads = 256);
315
319template<typename T>
321 const T* d_input, T* d_output, T* d_means, size_t n, fz::stream_t stream,
322 unsigned block_threads);
323
328template<typename T>
330 const T* d_input, const T* d_means, T* d_output, size_t n, fz::stream_t stream,
331 unsigned block_threads, int passes);
332
335template<typename T>
337 const T* d_input, T* d_output, T* d_means, size_t n, fz::stream_t stream,
338 unsigned block_threads);
339
340template<typename T>
341void launchLorenzoDeltaKernel2D(
342 const T* d_input, T* d_output, size_t nx, size_t ny, fz::stream_t stream);
343
344template<typename T>
345void launchLorenzoPrefixSumKernel2D(
346 const T* d_input, T* d_output, size_t nx, size_t ny, fz::stream_t stream);
347
348template<typename T>
349void launchLorenzoDeltaKernel3D(
350 const T* d_input, T* d_output, size_t nx, size_t ny, size_t nz, fz::stream_t stream);
351
352template<typename T>
353void launchLorenzoPrefixSumKernel3D(
354 const T* d_input, T* d_output, size_t nx, size_t ny, size_t nz, fz::stream_t stream);
355
356} // namespace fz
Definition lorenzo_stage.h:54
void setBlockSize(uint32_t n)
Definition lorenzo_stage.h:105
std::vector< size_t > estimateOutputSizes(const std::vector< size_t > &input_sizes) const override
Definition lorenzo_stage.h:198
size_t getMaxHeaderSize(size_t) const override
Definition lorenzo_stage.h:267
std::string getName() const override
Definition lorenzo_stage.h:183
size_t getActualOutputSize(int index) const override
Definition lorenzo_stage.h:213
uint16_t getStageTypeId() const override
Definition lorenzo_stage.h:219
void setInverse(bool inv) override
Definition lorenzo_stage.h:86
std::vector< std::string > getOutputNames() const override
Definition lorenzo_stage.h:193
void setCentering(bool enable)
Definition lorenzo_stage.h:141
size_t serializeHeader(size_t, uint8_t *buf, size_t max_size) const override
Definition lorenzo_stage.h:231
void setOrder(uint8_t k)
Definition lorenzo_stage.h:161
std::unordered_map< std::string, size_t > getActualOutputSizesByName() const override
Definition lorenzo_stage.h:207
uint8_t getInputDataType(size_t) const override
Definition lorenzo_stage.h:227
uint8_t getOutputDataType(size_t) const override
Definition lorenzo_stage.h:223
LorenzoStage(uint32_t block_size, bool centering=false, uint8_t order=1)
Definition lorenzo_stage.h:68
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 getNumInputs() const override
Centering adds a "means" port: a second output forward, a second input inverse.
Definition lorenzo_stage.h:186
void deserializeHeader(const uint8_t *buf, size_t size) override
Definition lorenzo_stage.h:247
void setDims(const std::array< size_t, 3 > &dims) override
Definition lorenzo_stage.h:89
Definition mempool.h:82
Definition stage.h:30
FZM binary file format definitions — structs, enums, and helpers.
Definition algorithms.h:48
void launchLorenzoDeltaCentered1D(const T *d_input, T *d_output, T *d_means, size_t n, fz::stream_t stream, unsigned block_threads)
void launchLorenzoSegmentedScan(const T *d_input, const T *d_means, T *d_output, size_t n, fz::stream_t stream, unsigned block_threads, int passes)
void launchLorenzo2Delta1D(const T *d_input, T *d_output, T *d_means, size_t n, fz::stream_t stream, unsigned block_threads)
constexpr size_t FZM_STAGE_CONFIG_SIZE
Per-stage serialized config slot (bytes)
Definition fzm_format.h:65
DataType
Element data type identifiers used in buffer and stage descriptors.
Definition fzm_format.h:118
Base class interface for all compression stages.
Definition lorenzo_stage.h:28
uint8_t centering
1 if per-block mean centering is enabled, else 0.
Definition lorenzo_stage.h:31
uint32_t dim_z
Z dimension (1 for 1-D/2-D).
Definition lorenzo_stage.h:35
DataType data_type
Signed integer element type (1B).
Definition lorenzo_stage.h:29
uint32_t dim_y
Y dimension (1 for 1-D).
Definition lorenzo_stage.h:34
uint8_t ndim
Spatial dimensionality 1/2/3 (0 treated as 1).
Definition lorenzo_stage.h:30
uint32_t dim_x
X (fast) dimension.
Definition lorenzo_stage.h:33
uint8_t order
Prediction order: 0/1 = first, 2 = second. 0 reads as 1.
Definition lorenzo_stage.h:32
uint32_t block_size
1-D block-local reset period; 0 = default N-D behavior.
Definition lorenzo_stage.h:36
Backend-neutral GPU type aliases.