21#include <unordered_map>
80 size_t legal_group_count = 0;
81 std::vector<SpecializationGroupInfo> installed_groups;
97 size_t input_data_size = 0,
99 float pool_multiplier = 3.0f
109 explicit Pipeline(
const std::string& config_path);
122 size_t getSpecializedGroupCount()
const {
return dag_ ? dag_->getFusedGroupCount() : 0; }
129 size_t getFusedGroupCount()
const {
return getSpecializedGroupCount(); }
133 void setNumStreams(
int num_streams);
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_; }
151 template<
typename StageT,
typename... Args>
152 StageT* addStage(Args&&... args);
161 int connect(
Stage* dependent,
Stage* producer,
const std::string& output_name =
"output");
164 int connect(
Stage* dependent,
const std::vector<Stage*>& producers);
189 void bindExternalInput(
Stage* stage);
203 void warmup(fz::stream_t stream = 0);
206 void setWarmupOnFinalize(
bool enable) { warmup_on_finalize_ = enable; }
207 bool isWarmupOnFinalizeEnabled()
const {
return warmup_on_finalize_; }
215 void setPoolManagedDecompOutput(
bool enable) { pool_managed_decomp_ = enable; }
216 bool isPoolManagedDecompOutput()
const {
return pool_managed_decomp_; }
250 void setPrimarySource(
Stage* stage) { primary_source_stage_ = stage; }
265 size_t getMaxCompressedSize(
size_t input_bytes)
const;
286 size_t getLastUncompressedSize()
const {
287 return original_input_size_ > 0 ? original_input_size_ : input_size_;
308 fz::stream_t stream = 0
341 size_t output_buf_capacity,
342 size_t* actual_output_size,
343 fz::stream_t stream = 0
365 fz::stream_t stream = 0
392 size_t output_buf_capacity,
393 size_t* actual_output_size,
394 fz::stream_t stream = 0
438 size_t output_buf_capacity,
439 size_t* actual_output_size,
440 fz::stream_t stream = 0
520 void prepareInverse(
size_t uncompressed_size);
523 void reset(fz::stream_t stream = 0);
531 void enableProfiling(
bool enable);
532 bool isProfilingEnabled()
const {
return profiling_enabled_; }
541 size_t getPoolThreshold()
const;
552 bool isMemPoolFallbackMode()
const;
559 void enableBoundsCheck(
bool enable) { dag_->enableBoundsCheck(enable); }
560 bool isBoundsCheckEnabled()
const {
return dag_->isBoundsCheckEnabled(); }
567 void setColoringEnabled(
bool enable) {
568 coloring_enabled_ = enable;
569 dag_->setColoringEnabled(enable);
571 bool isColoringEnabled()
const {
return dag_->isColoringEnabled(); }
572 size_t getColorRegionCount()
const {
return dag_->getColorRegionCount(); }
581 bool isColoringRequested()
const {
return coloring_enabled_; }
592 std::unordered_map<std::string, std::vector<std::string>> collectRunNotes()
const {
593 std::unordered_map<std::string, std::vector<std::string>> notes;
594 for (
const auto& s : stages_) {
596 auto n = s->getRunNotes();
597 if (!n.empty()) notes.emplace(s->getName(), std::move(n));
611 void enableGraphMode(
bool enable);
612 bool isGraphModeEnabled()
const {
return graph_mode_enabled_; }
624 void captureGraph(fz::stream_t stream = 0);
625 bool isGraphCaptured()
const {
return graph_captured_; }
627 size_t getPeakMemoryUsage()
const;
628 size_t getCurrentMemoryUsage()
const;
629 void printPipeline()
const;
636 std::vector<FZMStageInfo> stages;
637 std::vector<FZMBufferEntry> buffers;
641 void writeToFile(
const std::string& filename, fz::stream_t stream = 0);
644 static FZMFileHeader readHeader(
const std::string& filename);
665 std::vector<uint8_t> serializeHeaderToMemory()
const;
686 void primeInverseFromHeader(
const void* header_bytes,
size_t header_size);
702 static void decompressFromFile(
703 const std::string& filename,
706 fz::stream_t stream = 0,
708 size_t pool_override_bytes = 0
728 void decompressFromFileInstance(
729 const std::string& filename,
732 fz::stream_t stream = 0,
760 void decompressFromMemory(
761 const void* header_bytes,
767 fz::stream_t stream = 0
785 void loadConfig(
const std::string& path);
795 void saveConfig(
const std::string& path)
const;
806 ~PoolBuffer() { free(0); }
807 PoolBuffer() =
default;
808 PoolBuffer(
const PoolBuffer&) =
delete;
809 PoolBuffer& operator=(
const PoolBuffer&) =
delete;
811 void free(fz::stream_t s) {
812 if (ptr && pool) { pool->
free(ptr, s); ptr =
nullptr; capacity = 0; }
814 bool allocate(MemoryPool* p,
size_t bytes, fz::stream_t s,
815 const char* tag,
bool persistent =
false) {
818 ptr = pool->
allocate(bytes, s, tag, persistent);
819 if (ptr) capacity = bytes;
820 return ptr !=
nullptr;
825 struct PinnedBuffer {
829 ~PinnedBuffer() {
if (ptr) cudaFreeHost(ptr); }
830 PinnedBuffer() =
default;
831 PinnedBuffer(
const PinnedBuffer&) =
delete;
832 PinnedBuffer& operator=(
const PinnedBuffer&) =
delete;
835 bool ensureCapacity(
size_t bytes) {
836 if (capacity >= bytes)
return true;
837 if (ptr) { cudaFreeHost(ptr); ptr =
nullptr; capacity = 0; }
838 if (cudaHostAlloc(&ptr, bytes, cudaHostAllocDefault) != cudaSuccess)
return false;
845 struct DeviceBuffer {
849 ~DeviceBuffer() {
if (ptr) cudaFree(ptr); }
850 DeviceBuffer() =
default;
851 DeviceBuffer(
const DeviceBuffer&) =
delete;
852 DeviceBuffer& operator=(
const DeviceBuffer&) =
delete;
855 bool ensureCapacity(
size_t bytes) {
856 if (capacity >= bytes)
return true;
857 if (ptr) { cudaFree(ptr); ptr =
nullptr; capacity = 0; }
858 if (cudaMalloc(&ptr, bytes) != cudaSuccess)
return false;
866 Stage* addRawStage(Stage* stage);
868 struct OutputBuffer {
871 size_t allocated_size;
875 std::vector<OutputBuffer> getOutputBuffers()
const;
877 static void* loadCompressedData(
878 const std::string& filename,
879 const FZMFileHeader& header,
880 fz::stream_t stream = 0,
881 MemoryPool* pool =
nullptr
885 std::pair<std::vector<Stage*>, std::vector<Stage*>> identifyTopology();
886 void setupInputBuffers(
const std::vector<Stage*>& sources);
887 int autoDetectUnconnectedOutputs();
888 void detectMultiOutputScenario(
int pipeline_outputs);
889 void configureStreamsIfNeeded();
892 void typeCheckConnections();
893 void computeInputAlignment();
896 void bindSemanticContracts();
900 void planAndInstallFusion();
901 void notifyStagesFinalizeHooks();
902 void refinePoolSize();
903 void setupGraphModeInput();
904 void preallocatePadBuffer();
905 void preallocateConcatBuffers();
909 std::pair<const void*, size_t> prepareInputSource(
910 const void* d_input,
size_t input_size, fz::stream_t stream);
917 void propagateBufferSizes(
bool force_from_current_inputs =
false);
919 std::vector<Stage*> getSourceStages()
const;
920 std::vector<Stage*> getSinkStages()
const;
925 struct FwdStageDesc {
927 std::vector<int> output_buf_ids;
928 std::vector<int> input_buf_ids;
932 using PipelineOutputMap = std::unordered_map<int, std::pair<void*, size_t>>;
935 void buildOrReuseInvCache(
936 const PipelineOutputMap& po_map,
939 fz::stream_t stream);
949 std::vector<size_t> resolveDecompressSegmentSizes(
950 const void* d_input,
size_t input_size, fz::stream_t stream)
const;
958 PipelineOutputMap mapCompressedBufferPointers(
959 const void* d_input,
const std::vector<size_t>& seg_sizes)
const;
967 std::pair<Stage*, size_t> resolvePrimarySource()
const;
976 void* allocateDecompressOutput(
977 size_t actual_size,
void* caller_output,
size_t caller_capacity,
978 fz::stream_t stream);
996 size_t caller_capacity,
1000 fz::stream_t stream);
1009 void buildStaticBufferMetadata();
1016 std::vector<size_t> readConcatSegmentSizes(
1017 const void* d_blob,
size_t n, fz::stream_t stream)
const;
1021 static FZMFileHeader parseHeaderFromMemory(
const void* data,
size_t size);
1022 static size_t computeFilePoolSize(
const FZMFileHeader& fh,
size_t pool_override_bytes);
1023 static std::pair<std::vector<std::unique_ptr<Stage>>, std::vector<FwdStageDesc>>
1024 reconstructForwardTopology(
const FZMFileHeader& fh);
1025 static std::unordered_map<Stage*, size_t> buildSourceSizesFromHeader(
1026 const FZMFileHeader& fh,
const std::vector<FwdStageDesc>& fwd_topology);
1033 static std::pair<std::unique_ptr<CompressionDAG>,
1034 std::unordered_map<Stage*, int>>
1036 const std::vector<FwdStageDesc>& fwd_stages,
1037 const PipelineOutputMap& pipeline_outputs,
1040 const std::unordered_map<Stage*, size_t>& source_sizes,
1041 bool enable_profiling,
1042 bool enable_inverse_fusion =
false,
1045 bool caller_supplies_results =
false
1050 struct OutputBufferInfo {
1054 std::string stage_name;
1055 std::string output_name;
1058 std::vector<OutputBufferInfo> collectOutputBuffers()
const;
1061 size_t calculateConcatSize(
const std::vector<OutputBufferInfo>& outputs)
const;
1063 size_t writeConcatBuffer(
1064 const std::vector<OutputBufferInfo>& outputs,
1065 uint8_t* d_concat_bytes,
1069 void concatOutputs(
void** d_output,
size_t* output_size, fz::stream_t stream);
1073 std::unique_ptr<MemoryPool> mem_pool_;
1074 std::unique_ptr<CompressionDAG> dag_;
1077 std::vector<std::unique_ptr<Stage>> stages_;
1078 std::unordered_map<Stage*, DAGNode*> stage_to_node_;
1080 struct ConnectionInfo {
1083 std::string output_name;
1086 std::vector<ConnectionInfo> connections_;
1090 bool warmup_on_finalize_;
1091 bool pool_managed_decomp_;
1095 bool is_compressed_;
1096 bool was_compressed_;
1098 bool profiling_enabled_;
1101 bool coloring_enabled_ =
true;
1102 PipelinePerfResult last_perf_result_;
1104 std::vector<DAGNode*> input_nodes_;
1109 Stage* primary_source_stage_ =
nullptr;
1116 std::vector<std::pair<DAGNode*, int>> explicit_external_bindings_;
1117 std::vector<DAGNode*> output_nodes_;
1118 std::vector<int> input_buffer_ids_;
1119 std::vector<int> output_buffer_ids_;
1121 PoolBuffer d_concat_buffer_;
1126 std::vector<void*> d_decomp_outputs_;
1129 PinnedBuffer h_concat_header_;
1131 PinnedBuffer h_copy_descs_;
1132 DeviceBuffer d_copy_descs_;
1138 std::vector<size_t> source_input_sizes_;
1142 size_t input_alignment_bytes_;
1143 PoolBuffer d_pad_buf_;
1147 bool fused_source_unpadded_ =
false;
1151 size_t original_input_size_;
1153 size_t input_size_hint_;
1154 float pool_multiplier_;
1158 std::array<size_t, 3> dims_;
1168 struct InvDAGCache {
1169 std::unique_ptr<CompressionDAG> inv_dag;
1170 std::unordered_map<Stage*, int> inv_result_map;
1171 std::unordered_map<int, int> fwd_to_inv_ext_buf;
1172 std::unordered_map<Stage*, size_t> source_sizes;
1177 std::vector<size_t> fwd_size_signature;
1179 std::unique_ptr<InvDAGCache> inv_cache_;
1181 std::vector<size_t> forwardSizeSignature()
const;
1183 struct BufferMetadata {
1186 size_t allocated_size;
1191 std::vector<BufferMetadata> buffer_metadata_;
1193 bool graph_mode_enabled_;
1194 bool graph_captured_;
1200 PoolBuffer d_graph_input_;
1201 size_t d_graph_input_size_;
1203 fz::graph_t captured_graph_;
1204 fz::graph_exec_t graph_exec_;
1209template<
typename StageT,
typename... Args>
1210StageT* Pipeline::addStage(Args&&... args) {
1211 if (is_finalized_) {
1212 throw std::runtime_error(
"Cannot add stages after finalization");
1222 if constexpr (!StageT::isSupportedOnBackend()) {
1223 throw std::runtime_error(
1224 "addStage(): this stage type is not supported on the current "
1225 "GPU backend (FZGMOD_BACKEND) this library was built for");
1227 auto stage_ptr = std::make_unique<StageT>(std::forward<Args>(args)...);
1228 StageT* stage = stage_ptr.get();
1232 DAGNode* node = dag_->addStage(stage, stage->getName());
1233 size_t num_outputs = stage->getNumOutputs();
1234 auto output_names = stage->getOutputNames();
1238 for (
size_t i = 0; i < num_outputs; i++) {
1239 std::string out_name = i < output_names.size() ? output_names[i] : std::to_string(i);
1240 dag_->addUnconnectedOutput(node, 1, i, stage->getName() +
"." + out_name +
"_unconnected");
1243 stage_to_node_[stage] = node;
1244 stages_.push_back(std::move(stage_ptr));
Definition device_buffer.h:54
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
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.
Stream-ordered CUDA memory pool for pipeline buffer management.
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
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.