185 lines
5.5 KiB
Rust
185 lines
5.5 KiB
Rust
//! Integration tests for UniPC sampler
|
|
//!
|
|
//! Tests the complete workflow including scheduler integration
|
|
//! and compatibility with existing diffusion infrastructure.
|
|
|
|
use rtx_diffuse::{
|
|
DiffusionScheduler, NoiseGenerator, NoiseSchedule, PredictionType, Result, SchedulerType,
|
|
UniPCConfig, UniPCSampler,
|
|
};
|
|
use rtx_tensor::{Device, Tensor};
|
|
|
|
fn create_test_noise_generator() -> NoiseGenerator {
|
|
NoiseGenerator::new(
|
|
NoiseSchedule::Linear {
|
|
beta_start: 0.0001,
|
|
beta_end: 0.02,
|
|
},
|
|
1000,
|
|
Some(42),
|
|
)
|
|
.unwrap()
|
|
}
|
|
|
|
fn create_test_tensor(shape: Vec<usize>) -> Tensor {
|
|
let device = Device::cuda(0).unwrap_or(Device::default());
|
|
Tensor::randn(&shape, &device).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn test_unipc_scheduler_integration() {
|
|
// Create UniPC scheduler
|
|
let noise_gen = create_test_noise_generator();
|
|
let scheduler = DiffusionScheduler::new(
|
|
SchedulerType::UniPC {
|
|
predictor_order: 2,
|
|
corrector_order: 1,
|
|
use_corrector: true,
|
|
},
|
|
noise_gen,
|
|
10, // 10 inference steps for fast sampling
|
|
)
|
|
.unwrap();
|
|
|
|
let sample = create_test_tensor(vec![1, 3, 32, 32]);
|
|
let model_output = create_test_tensor(vec![1, 3, 32, 32]);
|
|
|
|
// Test scheduler step
|
|
let result = scheduler.step(&model_output, 500, &sample, None);
|
|
assert!(result.is_ok());
|
|
assert_eq!(result.unwrap().dims(), sample.dims());
|
|
|
|
// Test timesteps configuration
|
|
let timesteps = scheduler.timesteps();
|
|
assert_eq!(timesteps.len(), 10);
|
|
}
|
|
|
|
#[test]
|
|
fn test_unipc_standalone_sampler() {
|
|
let mut sampler =
|
|
UniPCSampler::new(UniPCConfig::default(), create_test_noise_generator()).unwrap();
|
|
|
|
let sample = create_test_tensor(vec![1, 3, 32, 32]);
|
|
let model_output = create_test_tensor(vec![1, 3, 32, 32]);
|
|
|
|
// Test full sampling workflow
|
|
let result = sampler.step(&model_output, 500, &sample).unwrap();
|
|
assert_eq!(result.dims(), sample.dims());
|
|
assert_eq!(sampler.stats().nfe, 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_unipc_fast_sampling() {
|
|
let mut sampler = UniPCSampler::new(
|
|
UniPCConfig {
|
|
predictor_order: 2,
|
|
corrector_order: 1,
|
|
use_corrector: true,
|
|
adaptive_order: false,
|
|
prediction_type: PredictionType::Epsilon,
|
|
variance_reduction: true,
|
|
corrector_iterations: 1,
|
|
max_order: 3,
|
|
},
|
|
create_test_noise_generator(),
|
|
)
|
|
.unwrap();
|
|
|
|
// Configure fast timesteps (7 steps)
|
|
let timesteps = sampler.configure_fast_timesteps(7).unwrap();
|
|
assert_eq!(timesteps.len(), 7);
|
|
|
|
let mut current_sample = create_test_tensor(vec![1, 3, 32, 32]);
|
|
let model_output = create_test_tensor(vec![1, 3, 32, 32]);
|
|
|
|
// Simulate 7-step sampling
|
|
for timestep in timesteps {
|
|
let step_result = sampler
|
|
.step(&model_output, timestep, ¤t_sample)
|
|
.unwrap();
|
|
current_sample = step_result;
|
|
}
|
|
|
|
// Verify sampling completed successfully
|
|
assert_eq!(sampler.stats().nfe, 7);
|
|
assert!(sampler.stats().predictor_steps >= 7);
|
|
assert_eq!(current_sample.dims(), &[1, 3, 32, 32]);
|
|
}
|
|
|
|
#[test]
|
|
fn test_unipc_adaptive_order() {
|
|
let mut sampler = UniPCSampler::new(
|
|
UniPCConfig {
|
|
adaptive_order: true,
|
|
max_order: 3,
|
|
..Default::default()
|
|
},
|
|
create_test_noise_generator(),
|
|
)
|
|
.unwrap();
|
|
|
|
// Test adaptive order selection
|
|
let (pred_order, corr_order) = sampler.select_adaptive_order(0.01, 10).unwrap();
|
|
assert!(pred_order >= 1 && pred_order <= 3);
|
|
assert!(corr_order >= 1 && corr_order <= 3);
|
|
|
|
// High error should prefer lower order
|
|
let (low_order, _) = sampler.select_adaptive_order(0.5, 5).unwrap();
|
|
let (high_order, _) = sampler.select_adaptive_order(0.01, 15).unwrap();
|
|
assert!(low_order <= high_order);
|
|
}
|
|
|
|
#[test]
|
|
fn test_prediction_type_conversions() {
|
|
let sampler = UniPCSampler::new(UniPCConfig::default(), create_test_noise_generator()).unwrap();
|
|
|
|
let sample = create_test_tensor(vec![1, 3, 32, 32]);
|
|
let model_output = create_test_tensor(vec![1, 3, 32, 32]);
|
|
|
|
// Test all prediction type conversions
|
|
let conversions = [
|
|
(PredictionType::Epsilon, PredictionType::Data),
|
|
(PredictionType::Epsilon, PredictionType::VPrediction),
|
|
(PredictionType::Data, PredictionType::Epsilon),
|
|
(PredictionType::VPrediction, PredictionType::Epsilon),
|
|
];
|
|
|
|
for (from_type, to_type) in conversions {
|
|
let result =
|
|
sampler.convert_prediction_type(&model_output, 500, &sample, from_type, to_type);
|
|
assert!(result.is_ok());
|
|
assert_eq!(result.unwrap().dims(), model_output.dims());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_unipc_error_conditions() {
|
|
// Test invalid configuration
|
|
let noise_gen = create_test_noise_generator();
|
|
assert!(
|
|
UniPCSampler::new(
|
|
UniPCConfig {
|
|
predictor_order: 0,
|
|
..Default::default()
|
|
},
|
|
noise_gen.clone()
|
|
)
|
|
.is_err()
|
|
);
|
|
assert!(
|
|
UniPCSampler::new(
|
|
UniPCConfig {
|
|
corrector_order: 5,
|
|
..Default::default()
|
|
},
|
|
noise_gen.clone()
|
|
)
|
|
.is_err()
|
|
);
|
|
|
|
// Test invalid timestep configuration
|
|
let sampler = UniPCSampler::new(UniPCConfig::default(), noise_gen).unwrap();
|
|
assert!(sampler.configure_fast_timesteps(0).is_err());
|
|
assert!(sampler.configure_fast_timesteps(2000).is_err());
|
|
}
|