Pruning Pipeline
The pruning pipeline manages the end-to-end workflow from model loading to compressed export. This chapter covers the pipeline stages and state machine.
Pipeline Stages
The pruning process follows a defined sequence of stages:
#![allow(unused)] fn main() { use entrenar::prune::PruningStage; let stages = [ PruningStage::Idle, // Initial state PruningStage::Calibrating, // Collecting activation statistics PruningStage::ComputingImportance,// Scoring weight importance PruningStage::Pruning, // Applying sparsity masks PruningStage::FineTuning, // Recovering accuracy PruningStage::Evaluating, // Validating quality PruningStage::Exporting, // Saving compressed model PruningStage::Complete, // Pipeline finished ]; }
Stage Details
Idle
Initial state before pruning begins.
#![allow(unused)] fn main() { let stage = PruningStage::Idle; assert!(!stage.is_active()); assert!(!stage.is_terminal()); }
Calibrating
Collects activation statistics for Wanda/SparseGPT methods.
#![allow(unused)] fn main() { let stage = PruningStage::Calibrating; assert!(stage.is_active()); println!("{}", stage.display_name()); // "Calibrating" }
Activities:
- Forward pass through calibration data
- Compute per-layer activation norms
- Build Hessian approximations (SparseGPT)
Skipped when: Using magnitude pruning (no calibration needed)
ComputingImportance
Scores each weight's importance using the configured method.
#![allow(unused)] fn main() { let stage = PruningStage::ComputingImportance; assert!(stage.is_active()); }
Activities:
- Apply importance formula (|w|, |w|*activation, Hessian-based)
- Compute statistics (min, max, mean, std)
- Validate for numerical stability (NaN, Inf)
Pruning
Generates and applies sparsity masks to zero out weights.
#![allow(unused)] fn main() { let stage = PruningStage::Pruning; assert!(stage.is_active()); }
Activities:
- Sort weights by importance
- Generate masks based on target sparsity and pattern
- Apply masks to model weights
- Verify achieved sparsity matches target
FineTuning
Recovers accuracy lost during pruning through continued training.
#![allow(unused)] fn main() { let stage = PruningStage::FineTuning; assert!(stage.is_active()); }
Activities:
- Continue training with frozen sparsity pattern
- Adjust learning rate (typically lower)
- Monitor loss convergence
- Apply gradient updates only to non-zero weights
Duration: Typically 10-20% of original training steps
Evaluating
Validates pruned model quality against benchmarks.
#![allow(unused)] fn main() { let stage = PruningStage::Evaluating; assert!(stage.is_active()); }
Activities:
- Run evaluation benchmarks
- Compare to baseline (unpruned) model
- Check quality gates (max accuracy drop)
- Generate evaluation report
Exporting
Saves the compressed model in deployment format.
#![allow(unused)] fn main() { let stage = PruningStage::Exporting; assert!(stage.is_active()); }
Activities:
- Convert to sparse storage format
- Apply additional compression (quantization)
- Save model weights and configuration
- Verify exported model loads correctly
Complete
Terminal state indicating successful pipeline completion.
#![allow(unused)] fn main() { let stage = PruningStage::Complete; assert!(!stage.is_active()); assert!(stage.is_terminal()); }
Stage Properties
Each stage exposes useful properties:
#![allow(unused)] fn main() { let stage = PruningStage::FineTuning; // Display name for UI println!("Stage: {}", stage.display_name()); // "Fine-tuning" // Check if actively processing if stage.is_active() { println!("Pipeline is working..."); } // Check if pipeline is done if stage.is_terminal() { println!("Pipeline complete!"); } }
Pipeline Flow Visualization
┌─────────┐
│ Idle │
└────┬────┘
│
▼
┌─────────────┐
│ Calibrating │ (skip if Magnitude)
└──────┬──────┘
│
▼
┌───────────────────┐
│ComputingImportance│
└─────────┬─────────┘
│
▼
┌─────────┐
│ Pruning │
└────┬────┘
│
▼
┌───────────┐
│FineTuning │
└─────┬─────┘
│
▼
┌───────────┐
│Evaluating │
└─────┬─────┘
│
▼
┌───────────┐
│ Exporting │
└─────┬─────┘
│
▼
┌──────────┐
│ Complete │
└──────────┘
Monitoring Pipeline Progress
Display pipeline status with stage indicators:
#![allow(unused)] fn main() { fn print_pipeline_status(current: PruningStage) { let stages = [ PruningStage::Idle, PruningStage::Calibrating, PruningStage::ComputingImportance, PruningStage::Pruning, PruningStage::FineTuning, PruningStage::Evaluating, PruningStage::Exporting, PruningStage::Complete, ]; for stage in &stages { let indicator = if *stage == current { if stage.is_active() { "🟢" } else { "✅" } } else { "⚪" }; println!("{} {}", indicator, stage.display_name()); } } }
Output:
✅ Idle
✅ Calibrating
🟢 Computing Importance ← Currently here
⚪ Pruning
⚪ Fine-tuning
⚪ Evaluating
⚪ Exporting
⚪ Complete
Error Handling
Pipeline stages can fail. Handle errors gracefully:
#![allow(unused)] fn main() { fn run_stage(stage: PruningStage) -> Result<(), PruneError> { match stage { PruningStage::Calibrating => { // Could fail if out of memory } PruningStage::ComputingImportance => { // Could fail with NaN/Inf weights } PruningStage::Pruning => { // Could fail with invalid pattern } // ... } Ok(()) } }
Best Practices
- Log stage transitions - Track timing and progress
- Checkpoint between stages - Enable restart on failure
- Validate at each stage - Catch issues early
- Monitor memory - Calibration and importance computation can spike
- Set quality gates - Define acceptable accuracy drop thresholds
Integration Example
Complete pipeline integration:
#![allow(unused)] fn main() { use entrenar::prune::{ PruningConfig, PruneMethod, PruningSchedule, SparsityPatternConfig, CalibrationConfig, PruningStage }; fn run_pruning_pipeline() { // Configure pruning let config = PruningConfig::new() .with_method(PruneMethod::Wanda) .with_target_sparsity(0.5) .with_pattern(SparsityPatternConfig::nm_2_4()) .with_schedule(PruningSchedule::OneShot { step: 0 }); // Configure calibration let calibration = CalibrationConfig::new() .with_num_samples(128) .with_sequence_length(2048) .with_dataset("c4"); // Validate before starting config.validate().expect("Invalid config"); // Run pipeline stages let stages = [ PruningStage::Calibrating, PruningStage::ComputingImportance, PruningStage::Pruning, PruningStage::FineTuning, PruningStage::Evaluating, PruningStage::Exporting, PruningStage::Complete, ]; for stage in &stages { println!("Starting: {}", stage.display_name()); // Execute stage... println!("Completed: {}", stage.display_name()); } } }