Skip to main content

torsh_benches/
lib.rs

1//! Benchmarking suite for ToRSh
2//!
3//! This crate provides comprehensive benchmarks for ToRSh to measure
4//! performance against other tensor libraries and track regressions.
5//!
6//! # Architecture
7//!
8//! The benchmarking suite is organized into specialized modules:
9//!
10//! - **core**: Core comparison infrastructure and performance analysis
11//! - **ndarray_comparisons**: ToRSh vs ndarray baseline comparisons
12//! - **pytorch_comparisons**: PyTorch integration benchmarks (feature-gated)
13//! - **tensorflow_comparisons**: TensorFlow comparison suite (feature-gated)
14//! - **jax_comparisons**: JAX performance benchmarks (feature-gated)
15//! - **numpy_comparisons**: NumPy baseline comparisons (feature-gated)
16//! - **reporting**: Comprehensive reporting and analysis utilities
17//!
18//! Additional specialized benchmarks include model-specific tests, hardware
19//! optimization benchmarks, edge deployment tests, and SciRS2 integration.
20
21#![cfg_attr(
22    not(any(feature = "tensorflow", feature = "pytorch", feature = "jax")),
23    allow(unexpected_cfgs)
24)]
25
26// Core comparison infrastructure
27pub mod core;
28
29// Specialized comparison modules
30pub mod ndarray_comparisons;
31pub mod reporting;
32
33// Feature-gated external library comparisons
34#[cfg(feature = "pytorch")]
35pub mod pytorch_comparisons;
36
37#[cfg(feature = "tensorflow")]
38pub mod tensorflow_comparisons;
39
40#[cfg(feature = "jax")]
41pub mod jax_comparisons;
42
43#[cfg(feature = "numpy_baseline")]
44pub mod numpy_comparisons;
45
46// Legacy comparison module (now clean interface)
47pub mod comparisons {
48    //! Legacy comparison interface that delegates to specialized modules
49    //!
50    //! This module maintains backward compatibility while providing access
51    //! to the new modular comparison architecture.
52
53    // Re-export core infrastructure
54    pub use crate::core::*;
55
56    // Re-export ndarray comparisons (always available)
57    pub use crate::ndarray_comparisons::*;
58
59    // Re-export feature-gated comparisons
60    #[cfg(feature = "pytorch")]
61    pub use crate::pytorch_comparisons::*;
62
63    #[cfg(feature = "tensorflow")]
64    pub use crate::tensorflow_comparisons::*;
65
66    #[cfg(feature = "jax")]
67    pub use crate::jax_comparisons::*;
68
69    #[cfg(feature = "numpy_baseline")]
70    pub use crate::numpy_comparisons::*;
71
72    // Re-export reporting utilities
73    pub use crate::reporting::*;
74}
75
76// Specialized benchmark modules
77pub mod advanced_analysis;
78pub mod benchmark_analysis;
79pub mod benchmark_cache;
80pub mod benchmark_comparison;
81pub mod benchmark_validation;
82pub mod benchmarks;
83pub mod cached_runner;
84pub mod ci_integration;
85pub mod custom_ops_benchmarks;
86pub mod distributed_training;
87pub mod edge_deployment;
88pub mod hardware_benchmarks;
89pub mod html_reporting;
90pub mod metrics;
91pub mod mobile_benchmarks;
92pub mod model_benchmarks;
93pub mod performance_dashboards;
94pub mod precision_benchmarks;
95pub mod regression_detection;
96pub mod scalability;
97pub mod scirs2_benchmarks;
98pub mod system_info;
99pub mod utils;
100pub mod visualization;
101pub mod wasm_benchmarks;
102
103// Core benchmarks
104pub use benchmarks::{
105    AdvancedSystemsBenchmarkSuite, AutoTuningBench, BackwardPassBench, DataLoaderThroughputBench,
106    ErrorDiagnosticsBench, GradientComputeBench, MatmulBench, SIMDGNNBench, TensorArithmeticBench,
107    TensorCreationBench, VectorizedMetricsBench,
108};
109
110// Core comparison framework
111pub use core::{ComparisonResult, ComparisonRunner, PerformanceAnalyzer};
112
113// Reporting utilities
114pub use reporting::{
115    benchmark_and_analyze, benchmark_and_analyze_to, benchmark_and_compare,
116    generate_master_comparison_report, generate_master_comparison_report_to,
117    run_all_comparison_suites, run_comparison_benchmarks, run_extended_benchmarks,
118};
119
120// Metrics and utilities
121pub use metrics::{CpuStats, MemoryStats, MetricsCollector, PerformanceReport, SystemMetrics};
122pub use utils::{
123    DataGenerator,
124    Distribution,
125    EnhancedBenchResult,
126    EnhancedBenchSuite,
127    Environment,
128    EnvironmentInfo,
129    Formatter,
130    MemoryMonitor,
131    ParallelBenchRunner,
132    Timer,
133    // Enhanced utilities
134    TimingStats,
135    ValidationResult,
136    Validator,
137};
138
139// Model benchmarks
140pub use model_benchmarks::{ModelBenchmarkSuite, ResNetBlockBench, TransformerBlockBench};
141
142// Scalability and hardware tests
143pub use hardware_benchmarks::{
144    CPUGPUComparisonBench, MemoryBandwidthBench, MultiGPUBench, ThermalThrottlingBench,
145};
146pub use scalability::ScalabilityTestSuite;
147
148// Precision and optimization benchmarks
149pub use precision_benchmarks::{MixedPrecisionTrainingBench, PruningBench, QuantizationBench};
150
151// Advanced benchmarks
152pub use custom_ops_benchmarks::{ConvolutionOperation, CustomOpBench, FFTOperation};
153pub use edge_deployment::{BatteryLifeBench, EdgeInferenceBench, EdgeMemoryBench};
154pub use mobile_benchmarks::{ARMOptimizationBench, MobileGPUBench, MobilePlatformBench};
155pub use wasm_benchmarks::{BrowserSpecificBench, WASMPerformanceBench, WebDeploymentBench};
156
157// SciRS2 integration benchmarks
158pub use scirs2_benchmarks::{
159    AdvancedNeuralNetworkBench, AdvancedOptimizerBench, GraphNeuralNetworkBench,
160    SciRS2BenchmarkSuite, SciRS2MathBench, SciRS2RandomBench, SpatialVisionBench,
161    TimeSeriesAnalysisBench,
162};
163
164// Reporting and analysis
165pub use advanced_analysis::{AdaptiveBenchmarking, AdvancedAnalyzer};
166pub use benchmark_analysis::{
167    BenchmarkAnalyzer, BottleneckAnalysis, PerformanceAnalysis, PerformanceRating,
168};
169pub use benchmark_validation::{BenchmarkValidator, NumericalAccuracy, ValidationConfig};
170pub use ci_integration::{CIBenchmarkRunner, CIConfig, NotificationConfig};
171pub use html_reporting::{HtmlReportGenerator, Theme};
172pub use performance_dashboards::{DashboardConfig, PerformanceDashboard};
173pub use regression_detection::{AdvancedRegressionDetector, RegressionAnalysis};
174pub use system_info::{BenchmarkEnvironment, SystemInfo, SystemInfoCollector};
175pub use visualization::{ChartType, VisualizationGenerator};
176
177use criterion::{BenchmarkId, Criterion, Throughput};
178use std::time::Duration;
179
180/// Trait for benchmarkable operations
181pub trait Benchmarkable {
182    type Input;
183    type Output;
184
185    /// Setup the benchmark input for a given size
186    fn setup(&mut self, size: usize) -> Self::Input;
187
188    /// Run the benchmark operation on the input
189    fn run(&mut self, input: &Self::Input) -> Self::Output;
190
191    /// Calculate the number of floating-point operations for a given size
192    fn flops(&self, size: usize) -> usize {
193        // Default implementation - can be overridden by specific benchmarks
194        size
195    }
196
197    /// Calculate the number of bytes accessed for a given size
198    fn bytes_accessed(&self, size: usize) -> usize {
199        // Default implementation - can be overridden by specific benchmarks
200        size * std::mem::size_of::<f32>()
201    }
202}
203
204/// Benchmark configuration
205#[derive(Debug, Clone)]
206pub struct BenchConfig {
207    /// Benchmark name
208    pub name: String,
209
210    /// Input sizes to test
211    pub sizes: Vec<usize>,
212
213    /// Data types to test
214    pub dtypes: Vec<torsh_core::dtype::DType>,
215
216    /// Number of warmup iterations
217    pub warmup_time: Duration,
218
219    /// Measurement time per size
220    pub measurement_time: Duration,
221
222    /// Whether to include memory usage metrics
223    pub measure_memory: bool,
224
225    /// Whether to include throughput metrics
226    pub measure_throughput: bool,
227
228    /// Custom metadata
229    pub metadata: std::collections::HashMap<String, String>,
230}
231
232impl Default for BenchConfig {
233    fn default() -> Self {
234        Self {
235            name: "default".to_string(),
236            sizes: vec![64, 256, 1024, 4096],
237            dtypes: vec![torsh_core::dtype::DType::F32],
238            warmup_time: Duration::from_millis(100),
239            measurement_time: Duration::from_secs(1),
240            measure_memory: false,
241            measure_throughput: true,
242            metadata: std::collections::HashMap::new(),
243        }
244    }
245}
246
247impl BenchConfig {
248    /// Create a new benchmark configuration
249    pub fn new(name: &str) -> Self {
250        Self {
251            name: name.to_string(),
252            ..Default::default()
253        }
254    }
255
256    /// Set input sizes
257    pub fn with_sizes(mut self, sizes: Vec<usize>) -> Self {
258        self.sizes = sizes;
259        self
260    }
261
262    /// Set data types
263    pub fn with_dtypes(mut self, dtypes: Vec<torsh_core::dtype::DType>) -> Self {
264        self.dtypes = dtypes;
265        self
266    }
267
268    /// Enable memory measurement
269    pub fn with_memory_measurement(mut self) -> Self {
270        self.measure_memory = true;
271        self
272    }
273
274    /// Set timing configuration
275    pub fn with_timing(mut self, warmup: Duration, measurement: Duration) -> Self {
276        self.warmup_time = warmup;
277        self.measurement_time = measurement;
278        self
279    }
280
281    /// Add metadata
282    pub fn with_metadata(mut self, key: &str, value: &str) -> Self {
283        self.metadata.insert(key.to_string(), value.to_string());
284        self
285    }
286}
287
288/// Benchmark result
289#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
290pub struct BenchResult {
291    /// Benchmark name
292    pub name: String,
293
294    /// Input size
295    pub size: usize,
296
297    /// Data type
298    pub dtype: torsh_core::dtype::DType,
299
300    /// Mean execution time in nanoseconds
301    pub mean_time_ns: f64,
302
303    /// Standard deviation of execution time
304    pub std_dev_ns: f64,
305
306    /// Throughput (operations per second)
307    pub throughput: Option<f64>,
308
309    /// Memory usage in bytes
310    pub memory_usage: Option<usize>,
311
312    /// Peak memory usage in bytes
313    pub peak_memory: Option<usize>,
314
315    /// Additional metrics
316    pub metrics: std::collections::HashMap<String, f64>,
317}
318
319impl BenchResult {
320    /// Get throughput in GFLOPS
321    pub fn gflops(&self, flops_per_op: usize) -> Option<f64> {
322        self.throughput.map(|tps| tps * flops_per_op as f64 / 1e9)
323    }
324
325    /// Get memory bandwidth in GB/s
326    pub fn memory_bandwidth_gbps(&self, bytes_per_op: usize) -> Option<f64> {
327        self.throughput.map(|tps| tps * bytes_per_op as f64 / 1e9)
328    }
329}
330
331/// Macro to create a simple benchmark
332#[macro_export]
333macro_rules! benchmark {
334    ($name:expr, $setup:expr, $run:expr) => {{
335        struct SimpleBench<S, R> {
336            setup_fn: S,
337            run_fn: R,
338        }
339
340        impl<S, R, I, O> $crate::Benchmarkable for SimpleBench<S, R>
341        where
342            S: FnMut(usize) -> I,
343            R: FnMut(&I) -> O,
344        {
345            type Input = I;
346            type Output = O;
347
348            fn setup(&mut self, size: usize) -> <Self as $crate::Benchmarkable>::Input {
349                (self.setup_fn)(size)
350            }
351
352            fn run(
353                &mut self,
354                input: &<Self as $crate::Benchmarkable>::Input,
355            ) -> <Self as $crate::Benchmarkable>::Output {
356                (self.run_fn)(input)
357            }
358        }
359
360        SimpleBench {
361            setup_fn: $setup,
362            run_fn: $run,
363        }
364    }};
365}
366
367/// Benchmark runner
368pub struct BenchRunner {
369    criterion: Criterion,
370    configs: Vec<BenchConfig>,
371    results: Vec<BenchResult>,
372}
373
374impl BenchRunner {
375    /// Create a new benchmark runner
376    pub fn new() -> Self {
377        Self {
378            criterion: Criterion::default()
379                .warm_up_time(Duration::from_millis(100))
380                .measurement_time(Duration::from_secs(1)),
381            configs: Vec::new(),
382            results: Vec::new(),
383        }
384    }
385
386    /// Add a benchmark configuration
387    pub fn add_config(mut self, config: BenchConfig) -> Self {
388        self.configs.push(config);
389        self
390    }
391
392    /// Run a benchmarkable operation
393    pub fn run_benchmark<B: Benchmarkable>(&mut self, mut bench: B, config: &BenchConfig) {
394        let mut group = self.criterion.benchmark_group(&config.name);
395        group.warm_up_time(config.warmup_time);
396        group.measurement_time(config.measurement_time);
397
398        for &size in &config.sizes {
399            for &dtype in &config.dtypes {
400                let bench_id = BenchmarkId::new(format!("{}_{:?}", config.name, dtype), size);
401
402                if config.measure_throughput {
403                    let bytes_per_op = bench.bytes_accessed(size);
404                    group.throughput(Throughput::Bytes(bytes_per_op as u64));
405                }
406
407                group.bench_with_input(bench_id, &size, |b, &size| {
408                    let input = bench.setup(size);
409
410                    b.iter(|| bench.run(&input));
411                });
412            }
413        }
414
415        group.finish();
416    }
417
418    /// Get benchmark results
419    pub fn results(&self) -> &[BenchResult] {
420        &self.results
421    }
422
423    /// Export results to CSV
424    pub fn export_csv(&self, path: &str) -> std::io::Result<()> {
425        use std::io::Write;
426        let mut file = std::fs::File::create(path)?;
427
428        writeln!(
429            file,
430            "name,size,dtype,mean_time_ns,std_dev_ns,throughput,memory_usage"
431        )?;
432
433        for result in &self.results {
434            writeln!(
435                file,
436                "{},{},{:?},{},{},{:?},{:?}",
437                result.name,
438                result.size,
439                result.dtype,
440                result.mean_time_ns,
441                result.std_dev_ns,
442                result.throughput,
443                result.memory_usage
444            )?;
445        }
446
447        Ok(())
448    }
449
450    /// Generate HTML report
451    pub fn generate_report(&self, output_dir: &str) -> std::io::Result<()> {
452        std::fs::create_dir_all(output_dir)?;
453
454        let report_path = format!("{}/benchmark_report.html", output_dir);
455        let mut file = std::fs::File::create(report_path)?;
456
457        use std::io::Write;
458        writeln!(file, "<!DOCTYPE html>")?;
459        writeln!(
460            file,
461            "<html><head><title>ToRSh Benchmark Report</title></head><body>"
462        )?;
463        writeln!(file, "<h1>ToRSh Benchmark Report</h1>")?;
464
465        // Add results table
466        writeln!(file, "<table border='1'>")?;
467        writeln!(file, "<tr><th>Benchmark</th><th>Size</th><th>Type</th><th>Time (μs)</th><th>Throughput</th></tr>")?;
468
469        for result in &self.results {
470            writeln!(
471                file,
472                "<tr><td>{}</td><td>{}</td><td>{:?}</td><td>{:.2}</td><td>{:.2}</td></tr>",
473                result.name,
474                result.size,
475                result.dtype,
476                result.mean_time_ns / 1000.0,
477                result.throughput.unwrap_or(0.0)
478            )?;
479        }
480
481        writeln!(file, "</table>")?;
482        writeln!(file, "</body></html>")?;
483
484        Ok(())
485    }
486}
487
488impl Default for BenchRunner {
489    fn default() -> Self {
490        Self::new()
491    }
492}
493
494/// Common benchmark utilities
495pub mod prelude {
496    pub use super::{benchmark, BenchConfig, BenchResult, BenchRunner};
497    pub use super::{BenchmarkAnalyzer, SystemInfoCollector};
498    pub use crate::benchmark_analysis::{BottleneckAnalysis, PerformanceAnalysis};
499    pub use crate::core::{ComparisonResult, ComparisonRunner, PerformanceAnalyzer};
500    pub use crate::system_info::{BenchmarkEnvironment, SystemInfo};
501    pub use crate::Benchmarkable;
502    pub use criterion::{BenchmarkId, Criterion, Throughput};
503    pub use std::hint::black_box;
504
505    // Enhanced utilities
506    pub use crate::utils::{
507        Distribution, EnhancedBenchResult, EnhancedBenchSuite, EnvironmentInfo, Formatter,
508        MemoryMonitor, ParallelBenchRunner, Timer, TimingStats, ValidationResult, Validator,
509    };
510}