feat: vendor midstream and sublinear-time-solver libraries

Add ruvnet/midstream (AIMDS real-time inference) and
ruvnet/sublinear-time-solver (sublinear optimization algorithms)
as vendored dependencies under vendor/.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv
2026-03-02 23:32:45 -05:00
parent 14902e6b4e
commit e91bb8a1d5
1600 changed files with 1852646 additions and 0 deletions
@@ -0,0 +1,104 @@
//! Performance benchmarks to validate optimizations against Python baselines
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
use sublinear_time_solver::fast_solver::{FastCSRMatrix, FastConjugateGradient};
use sublinear_time_solver::types::Precision;
fn generate_sparse_matrix(size: usize, sparsity: f64) -> (FastCSRMatrix, Vec<Precision>) {
let mut triplets = Vec::new();
let mut rng_state = 1u64;
// Generate diagonally dominant sparse matrix
for i in 0..size {
// Diagonal element (make it dominant)
let diag_val = 5.0 + (i as f64) * 0.01;
triplets.push((i, i, diag_val));
// Off-diagonal elements
let nnz_per_row = ((size as f64) * sparsity).max(1.0) as usize;
for _ in 0..nnz_per_row.min(5) {
// Simple LCG for reproducible random numbers
rng_state = rng_state.wrapping_mul(1103515245).wrapping_add(12345);
let j = (rng_state as usize) % size;
if i != j {
let val = (rng_state as f64 / u64::MAX as f64) * 0.5; // Keep small for diagonal dominance
triplets.push((i, j, val));
}
}
}
let matrix = FastCSRMatrix::from_triplets(triplets, size, size);
let b = vec![1.0; size]; // Simple right-hand side
(matrix, b)
}
fn bench_matrix_vector_multiply(c: &mut Criterion) {
let mut group = c.benchmark_group("matrix_vector_multiply");
for size in [100, 1000, 5000].iter() {
let (matrix, _) = generate_sparse_matrix(*size, 0.01);
let x = vec![1.0; *size];
group.bench_with_input(
BenchmarkId::new("fast_csr", size),
size,
|b, _| {
let mut y = vec![0.0; *size];
b.iter(|| {
matrix.multiply_vector_fast(black_box(&x), black_box(&mut y));
});
},
);
}
group.finish();
}
fn bench_conjugate_gradient_solve(c: &mut Criterion) {
let mut group = c.benchmark_group("conjugate_gradient_solve");
for size in [100, 1000].iter() {
let (matrix, b) = generate_sparse_matrix(*size, 0.01);
let solver = FastConjugateGradient::new(1000, 1e-8);
group.bench_with_input(
BenchmarkId::new("fast_cg", size),
size,
|bench, _| {
bench.iter(|| {
let _solution = solver.solve(black_box(&matrix), black_box(&b));
});
},
);
}
group.finish();
}
fn bench_sparse_dense_comparison(c: &mut Criterion) {
let mut group = c.benchmark_group("sparse_vs_dense");
// Test the critical 1000x1000 case that shows MCP Dense is 190x slower
let size = 1000;
let (sparse_matrix, b) = generate_sparse_matrix(size, 0.001); // Very sparse
let solver = FastConjugateGradient::new(100, 1e-6);
group.bench_function("optimized_sparse_1000x1000", |bench| {
bench.iter(|| {
let _solution = solver.solve(black_box(&sparse_matrix), black_box(&b));
});
});
group.finish();
}
criterion_group!(
benches,
bench_matrix_vector_multiply,
bench_conjugate_gradient_solve,
bench_sparse_dense_comparison
);
criterion_main!(benches);
@@ -0,0 +1,456 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId, Throughput};
use std::time::Duration;
use sublinear_time_solver::{
OptimizedSparseMatrix,
OptimizedConjugateGradientSolver,
OptimizedSolverConfig,
simd_ops::*,
matrix::sparse::{CSRStorage, COOStorage},
};
/// Generate a well-conditioned diagonally dominant test matrix
fn create_test_matrix(size: usize, sparsity: f64) -> OptimizedSparseMatrix {
let mut triplets = Vec::new();
let nnz_per_row = ((size as f64 * sparsity).max(3.0) as usize).min(size);
// Create strong diagonal dominance
for i in 0..size {
let diagonal_value = 10.0 + (i as f64 * 0.01);
triplets.push((i, i, diagonal_value));
// Add off-diagonal elements with magnitude < diagonal/nnz_per_row
let max_off_diagonal = diagonal_value / (nnz_per_row as f64 * 2.0);
let mut rng = i as u64 * 1664525 + 1013904223; // Simple LCG
for _ in 1..nnz_per_row {
rng = rng.wrapping_mul(1664525).wrapping_add(1013904223);
let col = (rng as usize) % size;
if col != i {
rng = rng.wrapping_mul(1664525).wrapping_add(1013904223);
let value = (rng as f64 / u64::MAX as f64) * max_off_diagonal;
triplets.push((i, col, value));
}
}
}
OptimizedSparseMatrix::from_triplets(triplets, size, size).unwrap()
}
/// Create a test right-hand side vector
fn create_test_rhs(size: usize) -> Vec<f64> {
(0..size).map(|i| 1.0 + (i as f64 * 0.001)).collect()
}
/// Benchmark SIMD vs non-SIMD matrix-vector multiplication
fn benchmark_simd_matvec(c: &mut Criterion) {
let sizes = vec![1000, 5000, 10000];
for size in sizes {
let matrix = create_test_matrix(size, 0.01);
let x = create_test_rhs(size);
let mut y = vec![0.0; size];
let mut group = c.benchmark_group("simd_matvec");
group.throughput(Throughput::Elements(size as u64));
group.measurement_time(Duration::from_secs(10));
group.bench_with_input(
BenchmarkId::new("simd", size),
&size,
|b, _| {
b.iter(|| {
matrix.multiply_vector(black_box(&x), black_box(&mut y));
});
},
);
group.finish();
}
}
/// Benchmark optimized conjugate gradient solver performance
fn benchmark_optimized_solver_scaling(c: &mut Criterion) {
let sizes = vec![100, 500, 1000, 2000, 5000];
let sparsity = 0.01;
let mut group = c.benchmark_group("optimized_solver_scaling");
group.measurement_time(Duration::from_secs(15));
for size in sizes {
if size > 1000 {
group.sample_size(10); // Reduce samples for large problems
}
let matrix = create_test_matrix(size, sparsity);
let b = create_test_rhs(size);
let config = OptimizedSolverConfig {
max_iterations: 1000,
tolerance: 1e-6,
enable_profiling: true,
};
group.throughput(Throughput::Elements((size * size) as u64));
group.bench_with_input(
BenchmarkId::new("cg_solver", size),
&size,
|bench, _| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(config.clone());
let result = solver.solve(black_box(&matrix), black_box(&b)).unwrap();
black_box(result)
});
},
);
}
group.finish();
}
/// Benchmark solver vs target performance metrics
fn benchmark_target_performance(c: &mut Criterion) {
// Target: 100K×100K system in < 150ms
let large_size = 10000; // Start with 10K for CI/testing, can scale to 100K
let matrix = create_test_matrix(large_size, 0.001); // Very sparse for 100K
let b = create_test_rhs(large_size);
let config = OptimizedSolverConfig {
max_iterations: 100, // Limited iterations for speed test
tolerance: 1e-3, // Relaxed tolerance for speed
enable_profiling: true,
};
let mut group = c.benchmark_group("target_performance");
group.measurement_time(Duration::from_secs(30));
group.sample_size(5);
group.bench_function("large_system_10k", |bench| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(config.clone());
let result = solver.solve(black_box(&matrix), black_box(&b)).unwrap();
// Validate convergence and performance
assert!(result.converged);
println!("Time: {:.2}ms, Iterations: {}, GFLOPS: {:.2}, Bandwidth: {:.2} GB/s",
result.computation_time_ms,
result.iterations,
result.performance_stats.average_gflops,
result.performance_stats.average_bandwidth_gbs
);
black_box(result)
});
});
group.finish();
}
/// Benchmark memory efficiency
fn benchmark_memory_efficiency(c: &mut Criterion) {
let sizes = vec![1000, 2000, 5000];
let mut group = c.benchmark_group("memory_efficiency");
group.measurement_time(Duration::from_secs(10));
for size in sizes {
let matrix = create_test_matrix(size, 0.02);
let b = create_test_rhs(size);
// Test different memory constraints
let memory_limits = vec![512, 1024, 2048]; // MB
for memory_limit in memory_limits {
let config = OptimizedSolverConfig {
max_iterations: 500,
tolerance: 1e-6,
enable_profiling: true,
};
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}x{}_{}MB", size, size, memory_limit)),
&(size, memory_limit),
|bench, _| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(config.clone());
let result = solver.solve(black_box(&matrix), black_box(&b)).unwrap();
// Check memory usage
let (matvec_count, bytes_processed) = matrix.get_performance_stats();
let estimated_memory_mb = (bytes_processed / 1_048_576) as f64;
println!("Size: {}, Memory limit: {}MB, Used: {:.2}MB, GFLOPS: {:.2}",
size, memory_limit, estimated_memory_mb,
result.performance_stats.average_gflops
);
black_box(result)
});
},
);
}
}
group.finish();
}
/// Benchmark sparsity impact on performance
fn benchmark_sparsity_performance(c: &mut Criterion) {
let size = 2000;
let sparsity_levels = vec![0.001, 0.005, 0.01, 0.02, 0.05];
let mut group = c.benchmark_group("sparsity_performance");
group.measurement_time(Duration::from_secs(10));
for sparsity in sparsity_levels {
let matrix = create_test_matrix(size, sparsity);
let b = create_test_rhs(size);
let config = OptimizedSolverConfig::default();
group.throughput(Throughput::Elements((matrix.nnz()) as u64));
group.bench_with_input(
BenchmarkId::from_parameter(format!("sparsity_{:.3}", sparsity)),
&sparsity,
|bench, _| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(config.clone());
let result = solver.solve(black_box(&matrix), black_box(&b)).unwrap();
println!("Sparsity: {:.3}, NNZ: {}, Time: {:.2}ms, GFLOPS: {:.2}",
sparsity, matrix.nnz(), result.computation_time_ms,
result.performance_stats.average_gflops
);
black_box(result)
});
},
);
}
group.finish();
}
/// Benchmark convergence characteristics
fn benchmark_convergence_analysis(c: &mut Criterion) {
let size = 1000;
let matrix = create_test_matrix(size, 0.01);
let b = create_test_rhs(size);
let tolerances = vec![1e-3, 1e-6, 1e-9, 1e-12];
let mut group = c.benchmark_group("convergence_analysis");
group.measurement_time(Duration::from_secs(15));
for tolerance in tolerances {
let config = OptimizedSolverConfig {
max_iterations: 5000,
tolerance,
enable_profiling: true,
};
group.bench_with_input(
BenchmarkId::from_parameter(format!("tol_{:.0e}", tolerance)),
&tolerance,
|bench, _| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(config.clone());
let result = solver.solve(black_box(&matrix), black_box(&b)).unwrap();
// Calculate convergence rate
let convergence_rate = if result.iterations > 1 {
(-result.residual_norm.ln()) / (result.iterations as f64)
} else {
0.0
};
println!("Tolerance: {:.0e}, Iterations: {}, Rate: {:.4}, Time: {:.2}ms",
tolerance, result.iterations, convergence_rate, result.computation_time_ms
);
// Verify we achieved the target tolerance
assert!(result.converged);
assert!(result.residual_norm <= tolerance * 10.0); // Allow some margin
black_box(result)
});
},
);
}
group.finish();
}
/// Comprehensive performance validation against all target metrics
fn benchmark_comprehensive_validation(c: &mut Criterion) {
let mut group = c.benchmark_group("comprehensive_validation");
group.measurement_time(Duration::from_secs(60));
group.sample_size(5);
// Test 1: Large system performance (scaled down for CI)
let large_size = 5000; // Would be 100K in production
let large_matrix = create_test_matrix(large_size, 0.0002); // Ultra-sparse
let large_b = create_test_rhs(large_size);
let fast_config = OptimizedSolverConfig {
max_iterations: 50,
tolerance: 1e-3,
enable_profiling: true,
};
group.bench_function("target_large_system", |bench| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(fast_config.clone());
let result = solver.solve(black_box(&large_matrix), black_box(&large_b)).unwrap();
// Target: < 150ms for 100K system (scaled proportionally)
let target_time_ms = 150.0 * (large_size as f64 / 100_000.0);
println!("Large system - Size: {}, Time: {:.2}ms (target: {:.2}ms), GFLOPS: {:.2}",
large_size, result.computation_time_ms, target_time_ms,
result.performance_stats.average_gflops
);
black_box(result)
});
});
// Test 2: Memory efficiency for 10K systems
let memory_size = 1000; // Would be 10K in production
let memory_matrix = create_test_matrix(memory_size, 0.01);
let memory_b = create_test_rhs(memory_size);
group.bench_function("target_memory_efficiency", |bench| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(OptimizedSolverConfig::default());
let result = solver.solve(black_box(&memory_matrix), black_box(&memory_b)).unwrap();
let (_, bytes_processed) = memory_matrix.get_performance_stats();
let memory_usage_mb = bytes_processed as f64 / 1_048_576.0;
// Target: < 1MB for 10K systems (scaled)
let target_memory_mb = 1.0 * (memory_size as f64 / 10_000.0);
println!("Memory test - Size: {}, Memory: {:.2}MB (target: {:.2}MB), Bandwidth: {:.2} GB/s",
memory_size, memory_usage_mb, target_memory_mb,
result.performance_stats.average_bandwidth_gbs
);
black_box(result)
});
});
// Test 3: Convergence rate for well-conditioned systems
let conv_size = 500;
let conv_matrix = create_test_matrix(conv_size, 0.02);
let conv_b = create_test_rhs(conv_size);
group.bench_function("target_convergence_rate", |bench| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(OptimizedSolverConfig::default());
let result = solver.solve(black_box(&conv_matrix), black_box(&conv_b)).unwrap();
// Target: > 90% convergence rate for well-conditioned systems
let convergence_success = result.converged;
let convergence_rate_percent = if convergence_success { 100.0 } else { 0.0 };
println!("Convergence test - Size: {}, Success: {}%, Iterations: {}, Residual: {:.2e}",
conv_size, convergence_rate_percent, result.iterations, result.residual_norm
);
assert!(convergence_success, "Should converge for well-conditioned system");
black_box(result)
});
});
group.finish();
}
/// Generate detailed performance report
fn benchmark_performance_report(c: &mut Criterion) {
let mut group = c.benchmark_group("performance_report");
group.measurement_time(Duration::from_secs(30));
group.sample_size(3);
let test_cases = vec![
(100, 0.05, "small_dense"),
(500, 0.02, "medium_sparse"),
(1000, 0.01, "large_sparse"),
(2000, 0.005, "very_large_very_sparse"),
];
for (size, sparsity, name) in test_cases {
let matrix = create_test_matrix(size, sparsity);
let b = create_test_rhs(size);
let config = OptimizedSolverConfig {
max_iterations: 1000,
tolerance: 1e-6,
enable_profiling: true,
};
group.bench_function(name, |bench| {
bench.iter(|| {
let mut solver = OptimizedConjugateGradientSolver::new(config.clone());
matrix.reset_stats();
let result = solver.solve(black_box(&matrix), black_box(&b)).unwrap();
let (matvec_count, bytes_processed) = matrix.get_performance_stats();
// Generate comprehensive report
println!("\n=== PERFORMANCE REPORT: {} ===", name);
println!("Matrix size: {}x{}", size, size);
println!("Sparsity: {:.3} ({} nnz)", sparsity, matrix.nnz());
println!("Time: {:.2} ms", result.computation_time_ms);
println!("Iterations: {}", result.iterations);
println!("Converged: {}", result.converged);
println!("Final residual: {:.2e}", result.residual_norm);
println!("Matrix-vector ops: {}", matvec_count);
println!("Dot products: {}", result.performance_stats.dot_product_count);
println!("AXPY operations: {}", result.performance_stats.axpy_count);
println!("Total FLOPS: {}", result.performance_stats.total_flops);
println!("Average GFLOPS: {:.2}", result.performance_stats.average_gflops);
println!("Average bandwidth: {:.2} GB/s", result.performance_stats.average_bandwidth_gbs);
println!("Bytes processed: {:.2} MB", bytes_processed as f64 / 1_048_576.0);
// Performance efficiency metrics
let flops_per_iteration = result.performance_stats.total_flops as f64 / result.iterations as f64;
let time_per_iteration = result.computation_time_ms / result.iterations as f64;
println!("FLOPS per iteration: {:.0}", flops_per_iteration);
println!("Time per iteration: {:.3} ms", time_per_iteration);
println!("Memory efficiency: {:.2} GB/s per GFLOP",
result.performance_stats.average_bandwidth_gbs / result.performance_stats.average_gflops.max(0.001));
// Check against targets
let meets_speed_target = result.computation_time_ms < 150.0 * (size as f64 / 100_000.0);
let meets_memory_target = (bytes_processed as f64 / 1_048_576.0) < 1.0 * (size as f64 / 10_000.0);
let meets_convergence_target = result.converged;
println!("Meets speed target: {}", meets_speed_target);
println!("Meets memory target: {}", meets_memory_target);
println!("Meets convergence target: {}", meets_convergence_target);
println!("=== END REPORT ===\n");
black_box(result)
});
});
}
group.finish();
}
criterion_group!(
performance_benches,
benchmark_simd_matvec,
benchmark_optimized_solver_scaling,
benchmark_target_performance,
benchmark_memory_efficiency,
benchmark_sparsity_performance,
benchmark_convergence_analysis,
benchmark_comprehensive_validation,
benchmark_performance_report
);
criterion_main!(performance_benches);
@@ -0,0 +1,423 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
use std::time::Duration;
use sublinear_time_solver::core::{SparseMatrix, Vector};
use sublinear_time_solver::solver::hybrid::{HybridSolver, HybridConfig};
use sublinear_time_solver::solver::random_walk::{RandomWalkEngine, RandomWalkConfig, BidirectionalWalk, VarianceReduction};
use sublinear_time_solver::solver::sampling::{AdaptiveSampler, SamplingConfig, SamplingStrategy, MultiLevelSampler};
use sublinear_time_solver::algorithms::Algorithm;
/// Create a test sparse matrix with given size and sparsity
fn create_benchmark_matrix(n: usize, sparsity: f64) -> SparseMatrix {
let mut matrix = SparseMatrix::new(n, n);
let num_nonzeros = (n * n) as f64 * sparsity;
// Create a symmetric positive definite matrix
for i in 0..n {
matrix.insert(i, i, 5.0 + i as f64 * 0.01); // Strong diagonal dominance
}
let mut rng = 12345u64; // Simple LCG for reproducible results
let mut added_elements = 0;
while added_elements < num_nonzeros as usize - n {
// Simple LCG
rng = rng.wrapping_mul(1664525).wrapping_add(1013904223);
let i = (rng as usize) % n;
rng = rng.wrapping_mul(1664525).wrapping_add(1013904223);
let j = (rng as usize) % n;
if i != j && !matrix.get_row(i).contains_key(&j) {
let value = (rng as f64 / u64::MAX as f64) * 0.5 - 0.25; // [-0.25, 0.25]
matrix.insert(i, j, value);
matrix.insert(j, i, value); // Symmetric
added_elements += 2;
}
}
matrix
}
/// Create a test vector
fn create_benchmark_vector(n: usize) -> Vector {
(0..n).map(|i| 1.0 + (i as f64) * 0.1).collect()
}
/// Benchmark random walk solver with different configurations
fn benchmark_random_walk_solver(c: &mut Criterion) {
let mut group = c.benchmark_group("random_walk_solver");
group.measurement_time(Duration::from_secs(20));
group.sample_size(10);
let sizes = vec![50, 100, 200];
let variance_methods = vec![
VarianceReduction::None,
VarianceReduction::Antithetic,
];
for size in sizes {
let matrix = create_benchmark_matrix(size, 0.1);
let b = create_benchmark_vector(size);
for method in &variance_methods {
let config = RandomWalkConfig {
max_steps: 5000,
variance_reduction: method.clone(),
convergence_tolerance: 1e-6,
seed: Some(42),
..Default::default()
};
let benchmark_id = BenchmarkId::from_parameter(format!("size_{}_method_{:?}", size, method));
group.bench_with_input(benchmark_id, &size, |b_bench, _| {
b_bench.iter(|| {
let mut engine = RandomWalkEngine::new(config.clone());
black_box(engine.solve_linear_system(&matrix, &b).unwrap())
});
});
}
}
group.finish();
}
/// Benchmark bidirectional random walk
fn benchmark_bidirectional_walk(c: &mut Criterion) {
let mut group = c.benchmark_group("bidirectional_walk");
group.measurement_time(Duration::from_secs(15));
group.sample_size(10);
let sizes = vec![30, 60, 120];
for size in sizes {
let matrix = create_benchmark_matrix(size, 0.15);
let b = create_benchmark_vector(size);
let config = RandomWalkConfig {
max_steps: 3000,
variance_reduction: VarianceReduction::Antithetic,
seed: Some(42),
..Default::default()
};
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b_bench, _| {
b_bench.iter(|| {
let mut solver = BidirectionalWalk::new(config.clone());
black_box(solver.solve_linear_system(&matrix, &b).unwrap())
});
});
}
group.finish();
}
/// Benchmark adaptive sampling strategies
fn benchmark_adaptive_sampling(c: &mut Criterion) {
let mut group = c.benchmark_group("adaptive_sampling");
group.measurement_time(Duration::from_secs(10));
group.sample_size(15);
let strategies = vec![
SamplingStrategy::Uniform,
SamplingStrategy::ImportanceSampling,
SamplingStrategy::AdaptiveSampling,
SamplingStrategy::QuasiMonteCarlo,
];
let domain_size = 1000;
let target_function = |x: usize| (x as f64 / 100.0).sin().abs() + 0.5;
for strategy in strategies {
let config = SamplingConfig {
strategy: strategy.clone(),
sample_size: 500,
seed: Some(42),
..Default::default()
};
group.bench_with_input(
BenchmarkId::from_parameter(format!("{:?}", strategy)),
&strategy,
|b_bench, _| {
b_bench.iter(|| {
let mut sampler = AdaptiveSampler::new(config.clone());
black_box(sampler.generate_samples(domain_size, &target_function).unwrap())
});
},
);
}
group.finish();
}
/// Benchmark multi-level sampling
fn benchmark_multilevel_sampling(c: &mut Criterion) {
let mut group = c.benchmark_group("multilevel_sampling");
group.measurement_time(Duration::from_secs(15));
group.sample_size(10);
let num_levels_vec = vec![2, 3, 4];
for num_levels in num_levels_vec {
let base_config = SamplingConfig {
sample_size: 1000,
seed: Some(42),
..Default::default()
};
let domain_sizes: Vec<usize> = (0..num_levels).map(|i| 1000 / (2_usize.pow(i as u32))).collect();
let target_functions: Vec<Box<dyn Fn(usize) -> f64>> = (0..num_levels)
.map(|level| {
Box::new(move |x: usize| {
(x as f64 / (10.0 * (level + 1) as f64)).sin().abs() + 0.1
}) as Box<dyn Fn(usize) -> f64>
})
.collect();
group.bench_with_input(
BenchmarkId::from_parameter(num_levels),
&num_levels,
|b_bench, _| {
b_bench.iter(|| {
let mut ml_sampler = MultiLevelSampler::new(num_levels, base_config.clone());
let fn_refs: Vec<&dyn Fn(usize) -> f64> = target_functions.iter().map(|f| f.as_ref()).collect();
black_box(ml_sampler.generate_multilevel_samples(&domain_sizes, &fn_refs).unwrap())
});
},
);
}
group.finish();
}
/// Benchmark hybrid solver with different configurations
fn benchmark_hybrid_solver(c: &mut Criterion) {
let mut group = c.benchmark_group("hybrid_solver");
group.measurement_time(Duration::from_secs(30));
group.sample_size(8);
let sizes = vec![40, 80, 160];
let configs = vec![
("deterministic_only", HybridConfig {
use_deterministic: true,
use_random_walk: false,
use_bidirectional: false,
use_multilevel: false,
max_iterations: 1000,
convergence_tolerance: 1e-6,
parallel_execution: false,
..Default::default()
}),
("random_walk_only", HybridConfig {
use_deterministic: false,
use_random_walk: true,
use_bidirectional: false,
use_multilevel: false,
max_iterations: 500,
convergence_tolerance: 1e-5,
parallel_execution: false,
random_walk_config: RandomWalkConfig {
max_steps: 3000,
variance_reduction: VarianceReduction::Antithetic,
seed: Some(42),
..Default::default()
},
..Default::default()
}),
("hybrid_approach", HybridConfig {
use_deterministic: true,
use_random_walk: true,
use_bidirectional: true,
use_multilevel: false,
deterministic_weight: 0.6,
max_iterations: 300,
convergence_tolerance: 1e-6,
parallel_execution: false,
adaptation_interval: 50,
..Default::default()
}),
];
for size in sizes {
let matrix = create_benchmark_matrix(size, 0.08);
let b = create_benchmark_vector(size);
for (config_name, config) in &configs {
let benchmark_id = BenchmarkId::from_parameter(format!("size_{}_config_{}", size, config_name));
group.bench_with_input(benchmark_id, &size, |b_bench, _| {
b_bench.iter(|| {
let mut solver = HybridSolver::new(config.clone());
black_box(solver.solve_linear_system(&matrix, &b).unwrap())
});
});
}
}
group.finish();
}
/// Benchmark parallel vs sequential execution
fn benchmark_parallel_vs_sequential(c: &mut Criterion) {
let mut group = c.benchmark_group("parallel_vs_sequential");
group.measurement_time(Duration::from_secs(25));
group.sample_size(5);
let size = 100;
let matrix = create_benchmark_matrix(size, 0.1);
let b = create_benchmark_vector(size);
let configs = vec![
("sequential", HybridConfig {
parallel_execution: false,
max_iterations: 200,
convergence_tolerance: 1e-5,
..Default::default()
}),
("parallel", HybridConfig {
parallel_execution: true,
max_iterations: 200,
convergence_tolerance: 1e-5,
..Default::default()
}),
];
for (mode, config) in configs {
group.bench_with_input(
BenchmarkId::from_parameter(mode),
&mode,
|b_bench, _| {
b_bench.iter(|| {
let mut solver = HybridSolver::new(config.clone());
black_box(solver.solve_linear_system(&matrix, &b).unwrap())
});
},
);
}
group.finish();
}
/// Benchmark convergence speed with different tolerances
fn benchmark_convergence_tolerance(c: &mut Criterion) {
let mut group = c.benchmark_group("convergence_tolerance");
group.measurement_time(Duration::from_secs(20));
group.sample_size(10);
let size = 60;
let matrix = create_benchmark_matrix(size, 0.12);
let b = create_benchmark_vector(size);
let tolerances = vec![1e-4, 1e-6, 1e-8];
for tolerance in tolerances {
let config = HybridConfig {
convergence_tolerance: tolerance,
max_iterations: 1000,
parallel_execution: false,
..Default::default()
};
group.bench_with_input(
BenchmarkId::from_parameter(format!("{:.0e}", tolerance)),
&tolerance,
|b_bench, _| {
b_bench.iter(|| {
let mut solver = HybridSolver::new(config.clone());
black_box(solver.solve_linear_system(&matrix, &b).unwrap())
});
},
);
}
group.finish();
}
/// Benchmark memory usage and performance correlation
fn benchmark_memory_performance(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_performance");
group.measurement_time(Duration::from_secs(15));
group.sample_size(8);
let size = 80;
let matrix = create_benchmark_matrix(size, 0.1);
let b = create_benchmark_vector(size);
let memory_limits = vec![512, 1024, 2048]; // MB
for memory_limit in memory_limits {
let config = HybridConfig {
memory_limit,
max_iterations: 500,
convergence_tolerance: 1e-6,
parallel_execution: false,
..Default::default()
};
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}MB", memory_limit)),
&memory_limit,
|b_bench, _| {
b_bench.iter(|| {
let mut solver = HybridSolver::new(config.clone());
let solution = solver.solve_linear_system(&matrix, &b).unwrap();
let metrics = solver.get_metrics();
black_box((solution, metrics.memory_usage))
});
},
);
}
group.finish();
}
/// Benchmark sparsity effects on performance
fn benchmark_sparsity_effects(c: &mut Criterion) {
let mut group = c.benchmark_group("sparsity_effects");
group.measurement_time(Duration::from_secs(20));
group.sample_size(10);
let size = 100;
let sparsity_levels = vec![0.05, 0.1, 0.2, 0.3];
for sparsity in sparsity_levels {
let matrix = create_benchmark_matrix(size, sparsity);
let b = create_benchmark_vector(size);
let config = HybridConfig {
max_iterations: 300,
convergence_tolerance: 1e-6,
parallel_execution: false,
..Default::default()
};
group.bench_with_input(
BenchmarkId::from_parameter(format!("sparsity_{:.2}", sparsity)),
&sparsity,
|b_bench, _| {
b_bench.iter(|| {
let mut solver = HybridSolver::new(config.clone());
black_box(solver.solve_linear_system(&matrix, &b).unwrap())
});
},
);
}
group.finish();
}
criterion_group!(
solver_benches,
benchmark_random_walk_solver,
benchmark_bidirectional_walk,
benchmark_adaptive_sampling,
benchmark_multilevel_sampling,
benchmark_hybrid_solver,
benchmark_parallel_vs_sequential,
benchmark_convergence_tolerance,
benchmark_memory_performance,
benchmark_sparsity_effects
);
criterion_main!(solver_benches);