FZGPUModules 2.0
GPU-accelerated modular compression pipelines
Loading...
Searching...
No Matches
compressor.h
Go to the documentation of this file.
1
5#pragma once
6
7#include "backend/types.h"
8#include "advanced/dag.h"
10#include "pipeline/perf.h"
11#include "pipeline/config.h"
12#include "stage/stage.h"
13#include "stage/stage_factory.h"
14#include "mem/mempool.h"
15#include "fzm_format.h"
16
17#include <array>
18#include <memory>
19#include <stdexcept>
20#include <string>
21#include <unordered_map>
22#include <vector>
23
24namespace fz {
25
63enum class SpecializationPolicy { Off, Auto, Force };
64
68
71 std::string implementation;
72 std::vector<std::string> stages;
73 std::string execution_path;
74};
76
79 SpecializationPolicy policy = SpecializationPolicy::Off;
80 size_t legal_group_count = 0;
81 std::vector<SpecializationGroupInfo> installed_groups;
83 std::vector<SpecializationGroupInfo> installed_inverse_groups;
85 std::string fallback_reason;
86};
88
89class Pipeline {
90public:
96 explicit Pipeline(
97 size_t input_data_size = 0,
99 float pool_multiplier = 3.0f
100 );
101
109 explicit Pipeline(const std::string& config_path);
110
111 ~Pipeline();
112
113 // ── Configuration ─────────────────────────────────────────────────────────
114
116 void setMemoryStrategy(MemoryStrategy strategy);
117
119 void setSpecializationPolicy(SpecializationPolicy mode) { fusion_policy_ = mode; }
120 SpecializationPolicy getSpecializationPolicy() const { return fusion_policy_; }
122 size_t getSpecializedGroupCount() const { return dag_ ? dag_->getFusedGroupCount() : 0; }
124 const SpecializationInfo& getSpecializationInfo() const { return fusion_info_; }
125
127 void setFusionPolicy(SpecializationPolicy mode) { setSpecializationPolicy(mode); }
128 SpecializationPolicy getFusionPolicy() const { return getSpecializationPolicy(); }
129 size_t getFusedGroupCount() const { return getSpecializedGroupCount(); }
130 const SpecializationInfo& getFusionInfo() const { return fusion_info_; }
131
133 void setNumStreams(int num_streams);
134
141 void setDims(size_t x, size_t y = 1, size_t z = 1) { dims_ = {x, y, z}; }
142 void setDims(std::array<size_t, 3> dims) { dims_ = dims; }
143 std::array<size_t, 3> getDims() const { return dims_; }
144
145 // ── Builder API ───────────────────────────────────────────────────────────
146
151 template<typename StageT, typename... Args>
152 StageT* addStage(Args&&... args);
153
161 int connect(Stage* dependent, Stage* producer, const std::string& output_name = "output");
162
164 int connect(Stage* dependent, const std::vector<Stage*>& producers);
165
189 void bindExternalInput(Stage* stage);
190
196 void finalize();
197
203 void warmup(fz::stream_t stream = 0);
204
206 void setWarmupOnFinalize(bool enable) { warmup_on_finalize_ = enable; }
207 bool isWarmupOnFinalizeEnabled() const { return warmup_on_finalize_; }
208
215 void setPoolManagedDecompOutput(bool enable) { pool_managed_decomp_ = enable; }
216 bool isPoolManagedDecompOutput() const { return pool_managed_decomp_; }
217
250 void setPrimarySource(Stage* stage) { primary_source_stage_ = stage; }
251
265 size_t getMaxCompressedSize(size_t input_bytes) const;
266
279 size_t getLastUncompressedSize() const {
280 return original_input_size_ > 0 ? original_input_size_ : input_size_;
281 }
282
283 // ── Execution ─────────────────────────────────────────────────────────────
284
296 void compress(
297 const void* d_input,
298 size_t input_size,
299 void** d_output,
300 size_t* output_size,
301 fz::stream_t stream = 0
302 );
303
330 void compress(
331 const void* d_input,
332 size_t input_size,
333 void* d_output_buf,
334 size_t output_buf_capacity,
335 size_t* actual_output_size,
336 fz::stream_t stream = 0
337 );
338
353 void decompress(
354 const void* d_input,
355 size_t input_size,
356 void** d_output,
357 size_t* output_size,
358 fz::stream_t stream = 0
359 );
360
380 void decompress(
381 const void* d_input,
382 size_t input_size,
383 void* d_output_buf,
384 size_t output_buf_capacity,
385 size_t* actual_output_size,
386 fz::stream_t stream = 0
387 );
388
426 void decompressInto(
427 const void* d_input,
428 size_t input_size,
429 void* d_output_buf,
430 size_t output_buf_capacity,
431 size_t* actual_output_size,
432 fz::stream_t stream = 0
433 );
434
435 // ── Explicit-ownership execution API ──────────────────────────────────────
436 //
437 // Span-based wrappers over the pointer overloads above. Behavior is
438 // identical — these exist so ownership is visible in the signature instead
439 // of depending on `void**` vs `void*` and on setPoolManagedDecompOutput().
440 // Prefer these in new code; the pointer overloads remain supported.
441
447 BorrowedDeviceBuffer compress(ConstDeviceSpan input, fz::stream_t stream = 0);
448
454 size_t compressInto(ConstDeviceSpan input, DeviceSpan output, fz::stream_t stream = 0);
455
464 BorrowedDeviceBuffer decompressBorrowed(ConstDeviceSpan input, fz::stream_t stream = 0);
465
471 OwnedDeviceBuffer decompressOwned(ConstDeviceSpan input, fz::stream_t stream = 0);
472
478 size_t decompressInto(ConstDeviceSpan input, DeviceSpan output, fz::stream_t stream = 0);
479
486 size_t decompressIntoAsync(ConstDeviceSpan input, DeviceSpan output, fz::stream_t stream = 0);
487
519 void prepareInverse(size_t uncompressed_size);
520
522 void reset(fz::stream_t stream = 0);
523
524 // ── Profiling ─────────────────────────────────────────────────────────────
525
530 void enableProfiling(bool enable);
531 bool isProfilingEnabled() const { return profiling_enabled_; }
532
534 const PipelinePerfResult& getLastPerfResult() const { return last_perf_result_; }
535
537 CompressionDAG* getDAG() { return dag_.get(); }
538
540 size_t getPoolThreshold() const;
541
551 bool isMemPoolFallbackMode() const;
552
558 void enableBoundsCheck(bool enable) { dag_->enableBoundsCheck(enable); }
559 bool isBoundsCheckEnabled() const { return dag_->isBoundsCheckEnabled(); }
560
566 void setColoringEnabled(bool enable) {
567 coloring_enabled_ = enable; // survives a setMemoryStrategy() DAG swap
568 dag_->setColoringEnabled(enable);
569 }
570 bool isColoringEnabled() const { return dag_->isColoringEnabled(); }
571 size_t getColorRegionCount() const { return dag_->getColorRegionCount(); }
572
580 bool isColoringRequested() const { return coloring_enabled_; }
581
591 std::unordered_map<std::string, std::vector<std::string>> collectRunNotes() const {
592 std::unordered_map<std::string, std::vector<std::string>> notes;
593 for (const auto& s : stages_) {
594 if (!s) continue;
595 auto n = s->getRunNotes();
596 if (!n.empty()) notes.emplace(s->getName(), std::move(n));
597 }
598 return notes;
599 }
600
601 // ── CUDA Graph Capture (compression-only) ─────────────────────────────────
602
610 void enableGraphMode(bool enable);
611 bool isGraphModeEnabled() const { return graph_mode_enabled_; }
612
623 void captureGraph(fz::stream_t stream = 0);
624 bool isGraphCaptured() const { return graph_captured_; }
625
626 size_t getPeakMemoryUsage() const;
627 size_t getCurrentMemoryUsage() const;
628 void printPipeline() const;
629
630 // ── File Serialization ────────────────────────────────────────────────────
631
634 FZMHeaderCore core;
635 std::vector<FZMStageInfo> stages;
636 std::vector<FZMBufferEntry> buffers;
637 };
638
640 void writeToFile(const std::string& filename, fz::stream_t stream = 0);
641
643 static FZMFileHeader readHeader(const std::string& filename);
644
646 FZMFileHeader buildHeader() const;
647
648 // ── In-memory metadata header (decode without a prior compress) ────────────
649
664 std::vector<uint8_t> serializeHeaderToMemory() const;
665
685 void primeInverseFromHeader(const void* header_bytes, size_t header_size);
686
693 static std::unique_ptr<Pipeline> fromHeader(
694 const void* header_bytes, size_t header_size,
696 SpecializationPolicy policy = SpecializationPolicy::Off);
697
712 static void decompressFromFile(
713 const std::string& filename,
714 void** d_output,
715 size_t* output_size,
716 fz::stream_t stream = 0,
717 PipelinePerfResult* perf_out = nullptr,
718 size_t pool_override_bytes = 0
719 );
720
738 void decompressFromFileInstance(
739 const std::string& filename,
740 void** d_output,
741 size_t* output_size,
742 fz::stream_t stream = 0,
743 PipelinePerfResult* perf_out = nullptr
744 );
745
770 void decompressFromMemory(
771 const void* header_bytes,
772 size_t header_size,
773 const void* d_blob,
774 size_t blob_size,
775 void** d_output,
776 size_t* output_size,
777 fz::stream_t stream = 0
778 );
779
780 // ── Config File ───────────────────────────────────────────────────────────
781
795 void loadConfig(const std::string& path);
796
805 void saveConfig(const std::string& path) const;
806
807private:
808 // ── RAII buffer wrappers (private implementation detail) ─────────────────
809
810 // Pool-allocated persistent device buffer.
811 struct PoolBuffer {
812 void* ptr = nullptr;
813 size_t capacity = 0;
814 MemoryPool* pool = nullptr;
815
816 ~PoolBuffer() { free(0); }
817 PoolBuffer() = default;
818 PoolBuffer(const PoolBuffer&) = delete;
819 PoolBuffer& operator=(const PoolBuffer&) = delete;
820
821 void free(fz::stream_t s) {
822 if (ptr && pool) { pool->free(ptr, s); ptr = nullptr; capacity = 0; }
823 }
824 bool allocate(MemoryPool* p, size_t bytes, fz::stream_t s,
825 const char* tag, bool persistent = false) {
826 free(s);
827 pool = p;
828 ptr = pool->allocate(bytes, s, tag, persistent);
829 if (ptr) capacity = bytes;
830 return ptr != nullptr;
831 }
832 };
833
834 // cudaHostAlloc pinned host buffer — grows on demand, never shrinks.
835 struct PinnedBuffer {
836 void* ptr = nullptr;
837 size_t capacity = 0;
838
839 ~PinnedBuffer() { if (ptr) cudaFreeHost(ptr); }
840 PinnedBuffer() = default;
841 PinnedBuffer(const PinnedBuffer&) = delete;
842 PinnedBuffer& operator=(const PinnedBuffer&) = delete;
843
844 // Returns false on CUDA allocation failure.
845 bool ensureCapacity(size_t bytes) {
846 if (capacity >= bytes) return true;
847 if (ptr) { cudaFreeHost(ptr); ptr = nullptr; capacity = 0; }
848 if (cudaHostAlloc(&ptr, bytes, cudaHostAllocDefault) != cudaSuccess) return false;
849 capacity = bytes;
850 return true;
851 }
852 };
853
854 // cudaMalloc device buffer — grows on demand, never shrinks.
855 struct DeviceBuffer {
856 void* ptr = nullptr;
857 size_t capacity = 0;
858
859 ~DeviceBuffer() { if (ptr) cudaFree(ptr); }
860 DeviceBuffer() = default;
861 DeviceBuffer(const DeviceBuffer&) = delete;
862 DeviceBuffer& operator=(const DeviceBuffer&) = delete;
863
864 // Returns false on CUDA allocation failure.
865 bool ensureCapacity(size_t bytes) {
866 if (capacity >= bytes) return true;
867 if (ptr) { cudaFree(ptr); ptr = nullptr; capacity = 0; }
868 if (cudaMalloc(&ptr, bytes) != cudaSuccess) return false;
869 capacity = bytes;
870 return true;
871 }
872 };
873
874 // ── Internal helpers ──────────────────────────────────────────────────────
875
876 Stage* addRawStage(Stage* stage);
877
878 struct OutputBuffer {
879 void* d_ptr;
880 size_t actual_size;
881 size_t allocated_size;
882 std::string name;
883 int buffer_id;
884 };
885 std::vector<OutputBuffer> getOutputBuffers() const;
886
887 static void* loadCompressedData(
888 const std::string& filename,
889 const FZMFileHeader& header,
890 fz::stream_t stream = 0,
891 MemoryPool* pool = nullptr
892 );
893
894 void validate();
895 std::pair<std::vector<Stage*>, std::vector<Stage*>> identifyTopology();
896 void setupInputBuffers(const std::vector<Stage*>& sources);
897 int autoDetectUnconnectedOutputs();
898 void detectMultiOutputScenario(int pipeline_outputs);
899 void configureStreamsIfNeeded();
900
901 // finalize() sub-steps
902 void typeCheckConnections();
903 void computeInputAlignment();
906 void bindSemanticContracts();
910 void planAndInstallFusion();
911 void notifyStagesFinalizeHooks();
912 void refinePoolSize();
913 void setupGraphModeInput();
914 void preallocatePadBuffer();
915 void preallocateConcatBuffers();
916
917 // compress() helper: handles graph-mode copy or alignment padding.
918 // Returns the effective source pointer and padded source size.
919 std::pair<const void*, size_t> prepareInputSource(
920 const void* d_input, size_t input_size, fz::stream_t stream);
921
927 void propagateBufferSizes(bool force_from_current_inputs = false);
928
929 std::vector<Stage*> getSourceStages() const;
930 std::vector<Stage*> getSinkStages() const;
931
932 // ── Inverse DAG helpers ───────────────────────────────────────────────────
933
935 struct FwdStageDesc {
936 Stage* stage;
937 std::vector<int> output_buf_ids;
938 std::vector<int> input_buf_ids;
939 };
940
942 using PipelineOutputMap = std::unordered_map<int, std::pair<void*, size_t>>;
943
944 // decompress() helper: builds or reuses the inverse DAG cache.
945 void buildOrReuseInvCache(
946 const PipelineOutputMap& po_map,
947 Stage* src_stage,
948 size_t src_sz,
949 fz::stream_t stream);
950
959 std::vector<size_t> resolveDecompressSegmentSizes(
960 const void* d_input, size_t input_size, fz::stream_t stream) const;
961
968 PipelineOutputMap mapCompressedBufferPointers(
969 const void* d_input, const std::vector<size_t>& seg_sizes) const;
970
977 std::pair<Stage*, size_t> resolvePrimarySource() const;
978
986 void* allocateDecompressOutput(
987 size_t actual_size, void* caller_output, size_t caller_capacity,
988 fz::stream_t stream);
989
1002 void decompressCore(
1003 const void* d_input,
1004 size_t input_size,
1005 void* caller_output,
1006 size_t caller_capacity,
1007 bool synchronize,
1008 void** d_output,
1009 size_t* output_size,
1010 fz::stream_t stream);
1011
1019 void buildStaticBufferMetadata();
1020
1026 std::vector<size_t> readConcatSegmentSizes(
1027 const void* d_blob, size_t n, fz::stream_t stream) const;
1028
1029 // decompressFromFile() helpers.
1031 static FZMFileHeader parseHeaderFromMemory(const void* data, size_t size);
1032 static size_t computeFilePoolSize(const FZMFileHeader& fh, size_t pool_override_bytes);
1033 static std::pair<std::vector<std::unique_ptr<Stage>>, std::vector<FwdStageDesc>>
1034 reconstructForwardTopology(const FZMFileHeader& fh);
1035 static std::unordered_map<Stage*, size_t> buildSourceSizesFromHeader(
1036 const FZMFileHeader& fh, const std::vector<FwdStageDesc>& fwd_topology);
1037
1043 static std::pair<std::unique_ptr<CompressionDAG>,
1044 std::unordered_map<Stage*, int>>
1045 buildInverseDAG(
1046 const std::vector<FwdStageDesc>& fwd_stages,
1047 const PipelineOutputMap& pipeline_outputs,
1048 MemoryPool* pool,
1049 MemoryStrategy strategy,
1050 const std::unordered_map<Stage*, size_t>& source_sizes,
1051 bool enable_profiling,
1052 bool enable_inverse_fusion = false,
1055 bool caller_supplies_results = false
1056 );
1057
1058 // ── Concat helpers ────────────────────────────────────────────────────────
1059
1060 struct OutputBufferInfo {
1061 int buffer_id;
1062 void* d_ptr;
1063 size_t actual_size;
1064 std::string stage_name;
1065 std::string output_name;
1066 };
1067
1068 std::vector<OutputBufferInfo> collectOutputBuffers() const;
1069
1071 size_t calculateConcatSize(const std::vector<OutputBufferInfo>& outputs) const;
1072
1073 size_t writeConcatBuffer(
1074 const std::vector<OutputBufferInfo>& outputs,
1075 uint8_t* d_concat_bytes,
1076 fz::stream_t stream
1077 ) const;
1078
1079 void concatOutputs(void** d_output, size_t* output_size, fz::stream_t stream);
1080
1081 // ── Member variables ──────────────────────────────────────────────────────
1082
1083 std::unique_ptr<MemoryPool> mem_pool_;
1084 std::unique_ptr<CompressionDAG> dag_;
1085 MemoryStrategy strategy_;
1086
1087 std::vector<std::unique_ptr<Stage>> stages_;
1088 std::unordered_map<Stage*, DAGNode*> stage_to_node_;
1089
1090 struct ConnectionInfo {
1091 Stage* dependent;
1092 Stage* producer;
1093 std::string output_name;
1094 int output_index;
1095 };
1096 std::vector<ConnectionInfo> connections_;
1097
1098 int num_streams_;
1099 bool is_finalized_;
1100 bool warmup_on_finalize_;
1101 bool pool_managed_decomp_;
1102
1103 // is_compressed_: true after the first successful compress() (gates writeToFile).
1104 // was_compressed_: true between compress() and the next reset() (gates captureGraph).
1105 bool is_compressed_;
1106 bool was_compressed_;
1107
1108 bool profiling_enabled_;
1111 bool coloring_enabled_ = true;
1112 PipelinePerfResult last_perf_result_;
1113
1114 std::vector<DAGNode*> input_nodes_;
1115 // Explicit choice of which input_nodes_ entry decompress() returns, for
1116 // pipelines with more than one source stage. Null = default to
1117 // input_nodes_[0]. Set via setPrimarySource(); resolved to an index lazily
1118 // (source stages aren't wired into input_nodes_ until finalize()).
1119 Stage* primary_source_stage_ = nullptr;
1120 // (node, buffer_id) pairs registered by bindExternalInput(), captured
1121 // immediately (before any later connect() calls add more buffer ids to
1122 // the same node). setupInputBuffers() appends these to input_nodes_/
1123 // input_buffer_ids_ after its own auto-discovery pass, since it clears
1124 // both first and auto-discovery alone would miss any stage that also
1125 // has real dependencies (getSourceStages() requires dependencies.empty()).
1126 std::vector<std::pair<DAGNode*, int>> explicit_external_bindings_;
1127 std::vector<DAGNode*> output_nodes_;
1128 std::vector<int> input_buffer_ids_;
1129 std::vector<int> output_buffer_ids_;
1130
1131 PoolBuffer d_concat_buffer_;
1132 bool needs_concat_;
1133
1134 // Pool-persistent decompress output buffers (one per source stage).
1135 // Only used when pool_managed_decomp_ == true.
1136 std::vector<void*> d_decomp_outputs_;
1137
1138 // Pinned host buffer for concat header (one H2D copy instead of N).
1139 PinnedBuffer h_concat_header_;
1140 // Persistent pinned host + device descriptor buffers for the gather kernel.
1141 PinnedBuffer h_copy_descs_;
1142 DeviceBuffer d_copy_descs_;
1143
1144 size_t input_size_;
1145
1146 // Per-source input sizes from the most recent compress(), ordered to match
1147 // input_nodes_. Used by decompress() to size each inverse result buffer.
1148 std::vector<size_t> source_input_sizes_;
1149
1150 // Input alignment in bytes — LCM of all stage getRequiredInputAlignment() values.
1151 // compress() zero-pads to this boundary transparently.
1152 size_t input_alignment_bytes_;
1153 PoolBuffer d_pad_buf_;
1157 bool fused_source_unpadded_ = false;
1158
1159 // Original (pre-padding) input size. decompress() uses this to trim the
1160 // reported output back to what the caller provided. 0 when no padding.
1161 size_t original_input_size_;
1162
1163 size_t input_size_hint_;
1164 float pool_multiplier_;
1165
1166 // Dataset dimensions (x=fast, y, z). Pushed to each stage on addStage() and
1167 // again at finalize(). Default {0,1,1} = 1-D, infer x from input size.
1168 std::array<size_t, 3> dims_;
1169
1178 struct InvDAGCache {
1179 std::unique_ptr<CompressionDAG> inv_dag;
1180 std::unordered_map<Stage*, int> inv_result_map;
1181 std::unordered_map<int, int> fwd_to_inv_ext_buf;
1182 std::unordered_map<Stage*, size_t> source_sizes;
1187 std::vector<size_t> fwd_size_signature;
1188 };
1189 std::unique_ptr<InvDAGCache> inv_cache_;
1191 std::vector<size_t> forwardSizeSignature() const;
1192
1193 struct BufferMetadata {
1194 int buffer_id;
1195 size_t actual_size;
1196 size_t allocated_size;
1197 std::string name;
1198 DAGNode* producer;
1199 int output_index;
1200 };
1201 std::vector<BufferMetadata> buffer_metadata_;
1202
1203 bool graph_mode_enabled_;
1204 bool graph_captured_;
1205 bool preserve_serialized_dims_ = false;
1206 FusionPolicy fusion_policy_ = FusionPolicy::Off;
1207 FusionInfo fusion_info_;
1208
1209 // Fixed device input buffer whose address is baked into the captured graph.
1210 // compress() copies user input here before cudaGraphLaunch().
1211 PoolBuffer d_graph_input_;
1212 size_t d_graph_input_size_;
1213
1214 fz::graph_t captured_graph_;
1215 fz::graph_exec_t graph_exec_;
1216};
1217
1218// ── Template implementation ───────────────────────────────────────────────────
1219
1220template<typename StageT, typename... Args>
1221StageT* Pipeline::addStage(Args&&... args) {
1222 if (is_finalized_) {
1223 throw std::runtime_error("Cannot add stages after finalization");
1224 }
1225
1226 // if constexpr, not a runtime check: on an unsupported backend, StageT's
1227 // constructor may not exist in the build at all (its .cu translation
1228 // unit excluded — see Stage::isSupportedOnBackend()'s doc comment), so
1229 // every line below that references `new StageT()` must never be
1230 // instantiated at all, not merely never executed — hence the whole rest
1231 // of the function lives in the `if constexpr` branch rather than after
1232 // a standalone early-throw.
1233 if constexpr (!StageT::isSupportedOnBackend()) {
1234 throw std::runtime_error(
1235 "addStage(): this stage type is not supported on the current "
1236 "GPU backend (FZGMOD_BACKEND) this library was built for");
1237 } else {
1238 auto stage_ptr = std::make_unique<StageT>(std::forward<Args>(args)...);
1239 StageT* stage = stage_ptr.get();
1240
1241 stage->setDims(dims_);
1242
1243 DAGNode* node = dag_->addStage(stage, stage->getName());
1244 size_t num_outputs = stage->getNumOutputs();
1245 auto output_names = stage->getOutputNames();
1246
1247 // Pre-allocate all output slots as unconnected (size=1 placeholder).
1248 // connect() will promote any that get wired to downstream stages.
1249 for (size_t i = 0; i < num_outputs; i++) {
1250 std::string out_name = i < output_names.size() ? output_names[i] : std::to_string(i);
1251 dag_->addUnconnectedOutput(node, 1, i, stage->getName() + "." + out_name + "_unconnected");
1252 }
1253
1254 stage_to_node_[stage] = node;
1255 stages_.push_back(std::move(stage_ptr));
1256 return stage;
1257 }
1258}
1259
1260} // namespace fz
Definition device_buffer.h:54
Definition dag.h:104
Definition mempool.h:82
void free(void *ptr, fz::stream_t stream)
void * allocate(size_t size, fz::stream_t stream, const std::string &tag="", bool persistent=false)
Definition device_buffer.h:84
Definition stage.h:31
virtual void setDims(const std::array< size_t, 3 > &dims)
Definition stage.h:207
TOML-based pipeline configuration file support.
Compression DAG wiring, execution, and memory strategy types.
Backend-neutral device span and buffer value types.
FZM binary file format definitions — structs, enums, and helpers.
Stream-ordered CUDA memory pool for pipeline buffer management.
Definition dag.h:24
SpecializationPolicy
Pipeline Specialization policy.
Definition compressor.h:63
MemoryStrategy
Definition dag.h:32
@ MINIMAL
Allocate on-demand, free at last consumer. Lowest peak memory.
SpecializationInfo FusionInfo
Definition compressor.h:87
SpecializationPolicy FusionPolicy
Definition compressor.h:67
Pipeline and per-stage profiling result types.
Base class interface for all compression stages.
Backward-compatible shim.
Definition device_buffer.h:35
Definition device_buffer.h:24
Fixed-size FZM file header core (80 bytes).
Definition fzm_format.h:275
Definition perf.h:78
Definition compressor.h:633
One finalize-time specialization selected for execution (compress or inverse).
Definition compressor.h:70
std::vector< std::string > stages
the stages it replaced
Definition compressor.h:72
std::string execution_path
last runtime subpath; empty if not applicable
Definition compressor.h:73
std::string implementation
strategy impl name, e.g. "warp-register"
Definition compressor.h:71
Resolved specialization decision for diagnostics and benchmark provenance.
Definition compressor.h:78
std::string fallback_reason
policy_off, no_legal_group, or legacy no_profitable_implementation; empty on a hit.
Definition compressor.h:85
std::vector< SpecializationGroupInfo > installed_inverse_groups
Lazily populated after the first decompress builds its inverse DAG.
Definition compressor.h:83
Backend-neutral GPU type aliases.