1use crate::common::StateMemoryStats;
35use std::collections::HashMap;
36use trustformers_core::errors::Result;
37use trustformers_core::tensor::Tensor;
38use trustformers_core::traits::Optimizer;
39
40pub trait StatefulOptimizer: Optimizer {
45 type Config: Clone + Send + Sync;
47
48 type State: Send + Sync;
50
51 fn config(&self) -> &Self::Config;
53
54 fn state(&self) -> &Self::State;
56
57 fn state_mut(&mut self) -> &mut Self::State;
59
60 fn state_dict(&self) -> Result<HashMap<String, Tensor>>;
62
63 fn load_state_dict(&mut self, state: HashMap<String, Tensor>) -> Result<()>;
65
66 fn memory_usage(&self) -> StateMemoryStats;
68
69 fn reset_state(&mut self);
71
72 fn num_parameters(&self) -> usize;
74}
75
76pub trait MomentumOptimizer: StatefulOptimizer {
80 fn momentum_coeff(&self) -> f32;
82
83 fn set_momentum_coeff(&mut self, coeff: f32);
85
86 fn momentum_buffers(&self) -> &HashMap<String, Vec<f32>>;
88
89 fn clear_momentum(&mut self);
91}
92
93pub trait AdaptiveMomentumOptimizer: MomentumOptimizer {
97 fn variance_coeff(&self) -> f32;
99
100 fn set_variance_coeff(&mut self, coeff: f32);
102
103 fn epsilon(&self) -> f32;
105
106 fn set_epsilon(&mut self, eps: f32);
108
109 fn variance_buffers(&self) -> &HashMap<String, Vec<f32>>;
111
112 fn clear_variance(&mut self);
114
115 fn apply_bias_correction(&self, momentum: f32, variance: f32, step: usize) -> (f32, f32);
117}
118
119pub trait ClassicalMomentumOptimizer: MomentumOptimizer {
121 fn dampening(&self) -> f32;
123
124 fn set_dampening(&mut self, dampening: f32);
126
127 fn nesterov(&self) -> bool;
129
130 fn set_nesterov(&mut self, nesterov: bool);
132}
133
134pub trait SecondOrderOptimizer: StatefulOptimizer {
138 type CurvatureInfo;
140
141 fn update_curvature(&mut self, gradients: &[Tensor]) -> Result<()>;
143
144 fn curvature_info(&self) -> &Self::CurvatureInfo;
146
147 fn apply_inverse_hessian(&self, gradient: &Tensor) -> Result<Tensor>;
149
150 fn history_size(&self) -> usize;
152}
153
154pub trait DistributedOptimizer: Optimizer {
158 type Communicator;
160
161 fn all_reduce_gradients(&mut self, gradients: &mut [Tensor]) -> Result<()>;
163
164 fn broadcast_parameters(&mut self, parameters: &mut [Tensor]) -> Result<()>;
166
167 fn rank(&self) -> usize;
169
170 fn world_size(&self) -> usize;
172
173 fn sync_state(&mut self) -> Result<()>;
175}
176
177pub trait GradientCompressionOptimizer: DistributedOptimizer {
179 type CompressionMethod;
181
182 fn compress_gradients(&self, gradients: &[Tensor]) -> Result<Vec<u8>>;
184
185 fn decompress_gradients(&self, data: &[u8]) -> Result<Vec<Tensor>>;
187
188 fn compression_ratio(&self) -> f32;
190
191 fn set_compression_config(&mut self, config: Self::CompressionMethod);
193}
194
195pub trait FederatedOptimizer: DistributedOptimizer {
197 type ClientInfo;
199
200 fn aggregate_updates(
202 &mut self,
203 updates: &[Tensor],
204 clients: &[Self::ClientInfo],
205 ) -> Result<Tensor>;
206
207 fn select_clients(
209 &self,
210 available_clients: &[Self::ClientInfo],
211 num_clients: usize,
212 ) -> Vec<usize>;
213
214 fn apply_differential_privacy(&mut self, update: &mut Tensor) -> Result<()>;
216}
217
218pub trait AsyncOptimizer: DistributedOptimizer {
220 fn apply_delayed_gradients(&mut self, gradients: &[Tensor], staleness: usize) -> Result<()>;
222
223 fn max_staleness(&self) -> usize;
225
226 fn set_staleness_compensation(&mut self, method: StalenessCompensation);
228}
229
230#[derive(Debug, Clone, Copy)]
232pub enum StalenessCompensation {
233 None,
235 Linear,
237 Exponential,
239 Polynomial(f32),
241}
242
243pub trait HardwareOptimizer: Optimizer {
245 type HardwareTarget;
247
248 fn optimize_for_hardware(&mut self, target: Self::HardwareTarget) -> Result<()>;
250
251 fn hardware_utilization(&self) -> HardwareStats;
253
254 fn is_hardware_compatible(&self) -> bool;
256}
257
258#[derive(Debug, Clone)]
260pub struct HardwareStats {
261 pub memory_bandwidth_utilization: f32,
263 pub compute_utilization: f32,
265 pub cache_hit_rate: f32,
267 pub flops_per_second: f64,
269}
270
271pub trait SIMDOptimizer: HardwareOptimizer {
273 type SIMDType;
275
276 fn simd_available(&self) -> bool;
278
279 fn vector_width(&self) -> usize;
281
282 fn simd_update(&mut self, parameters: &mut [Tensor], gradients: &[Tensor]) -> Result<()>;
284}
285
286pub trait GPUOptimizer: HardwareOptimizer {
288 type ComputeCapability;
290
291 fn to_gpu(&mut self) -> Result<()>;
293
294 fn to_cpu(&mut self) -> Result<()>;
296
297 fn gpu_update(&mut self, parameters: &mut [Tensor], gradients: &[Tensor]) -> Result<()>;
299
300 fn gpu_memory_usage(&self) -> GPUMemoryStats;
302}
303
304#[derive(Debug, Clone)]
306pub struct GPUMemoryStats {
307 pub total_memory: usize,
309 pub used_memory: usize,
311 pub available_memory: usize,
313 pub optimizer_memory: usize,
315}
316
317pub trait EdgeOptimizer: HardwareOptimizer {
319 type PowerStats;
321
322 fn optimize_for_power(&mut self) -> Result<()>;
324
325 fn power_stats(&self) -> Self::PowerStats;
327
328 fn reduce_precision(&mut self, bits: u8) -> Result<()>;
330}
331
332pub trait MetaOptimizer: Optimizer {
334 type BaseOptimizer: Optimizer;
336
337 fn base_optimizer(&self) -> &Self::BaseOptimizer;
339
340 fn base_optimizer_mut(&mut self) -> &mut Self::BaseOptimizer;
342
343 fn apply_meta_strategy(
345 &mut self,
346 parameters: &mut [Tensor],
347 gradients: &[Tensor],
348 ) -> Result<()>;
349}
350
351pub trait LookaheadOptimizer: MetaOptimizer {
353 fn lookahead_alpha(&self) -> f32;
355
356 fn set_lookahead_alpha(&mut self, alpha: f32);
358
359 fn lookahead_k(&self) -> usize;
361
362 fn set_lookahead_k(&mut self, k: usize);
364
365 fn slow_weights(&self) -> &HashMap<String, Vec<f32>>;
367}
368
369pub trait ScheduledOptimizer: Optimizer {
371 type Scheduler;
373
374 fn scheduler(&self) -> &Self::Scheduler;
376
377 fn scheduler_mut(&mut self) -> &mut Self::Scheduler;
379
380 fn update_lr(&mut self) -> Result<()>;
382
383 fn current_lr(&self) -> f32;
385}
386
387pub trait CompositeOptimizer: Optimizer {
389 type Components;
391
392 fn components(&self) -> &Self::Components;
394
395 fn components_mut(&mut self) -> &mut Self::Components;
397
398 fn apply_composite_update(
400 &mut self,
401 parameters: &mut [Tensor],
402 gradients: &[Tensor],
403 ) -> Result<()>;
404
405 fn component_weights(&self) -> Vec<f32>;
407
408 fn set_component_weights(&mut self, weights: Vec<f32>) -> Result<()>;
410}
411
412pub trait OptimizerFactory {
414 type Optimizer: Optimizer;
416
417 type Config;
419
420 fn create(&self, config: Self::Config) -> Result<Self::Optimizer>;
422
423 fn available_variants(&self) -> Vec<&'static str>;
425
426 fn create_by_name(&self, name: &str) -> Result<Self::Optimizer>;
428}
429
430pub trait SerializableOptimizer: Optimizer {
432 fn serialize(&self) -> Result<Vec<u8>>;
434
435 fn deserialize(data: &[u8]) -> Result<Self>
437 where
438 Self: Sized;
439
440 fn version(&self) -> u32;
442}
443
444#[cfg(test)]
445mod tests {
446 use super::*;
447
448 #[test]
449 fn test_staleness_compensation() {
450 let compensation = StalenessCompensation::Linear;
451 assert!(
452 matches!(compensation, StalenessCompensation::Linear),
453 "Expected Linear staleness compensation"
454 );
455 }
456
457 #[test]
458 fn test_hardware_stats() {
459 let stats = HardwareStats {
460 memory_bandwidth_utilization: 0.8,
461 compute_utilization: 0.9,
462 cache_hit_rate: 0.95,
463 flops_per_second: 1e12,
464 };
465
466 assert_eq!(stats.memory_bandwidth_utilization, 0.8);
467 assert_eq!(stats.compute_utilization, 0.9);
468 assert_eq!(stats.cache_hit_rate, 0.95);
469 assert_eq!(stats.flops_per_second, 1e12);
470 }
471
472 #[test]
473 fn test_gpu_memory_stats() {
474 let stats = GPUMemoryStats {
475 total_memory: 16 * 1024 * 1024 * 1024, used_memory: 8 * 1024 * 1024 * 1024, available_memory: 8 * 1024 * 1024 * 1024, optimizer_memory: 1024 * 1024 * 1024, };
480
481 assert_eq!(stats.total_memory, 16 * 1024 * 1024 * 1024);
482 assert_eq!(
483 stats.used_memory + stats.available_memory,
484 stats.total_memory
485 );
486 assert!(stats.optimizer_memory <= stats.used_memory);
487 }
488
489 #[test]
490 fn test_staleness_compensation_none() {
491 let comp = StalenessCompensation::None;
492 assert!(matches!(comp, StalenessCompensation::None));
493 }
494
495 #[test]
496 fn test_staleness_compensation_exponential() {
497 let comp = StalenessCompensation::Exponential;
498 assert!(matches!(comp, StalenessCompensation::Exponential));
499 }
500
501 #[test]
502 fn test_staleness_compensation_polynomial() {
503 let comp = StalenessCompensation::Polynomial(2.0);
504 if let StalenessCompensation::Polynomial(degree) = comp {
505 assert_eq!(degree, 2.0);
506 } else {
507 panic!("Expected Polynomial variant");
508 }
509 }
510
511 #[test]
512 fn test_hardware_stats_all_zero() {
513 let stats = HardwareStats {
514 memory_bandwidth_utilization: 0.0,
515 compute_utilization: 0.0,
516 cache_hit_rate: 0.0,
517 flops_per_second: 0.0,
518 };
519 assert_eq!(stats.memory_bandwidth_utilization, 0.0);
520 assert_eq!(stats.flops_per_second, 0.0);
521 }
522
523 #[test]
524 fn test_hardware_stats_max_utilization() {
525 let stats = HardwareStats {
526 memory_bandwidth_utilization: 1.0,
527 compute_utilization: 1.0,
528 cache_hit_rate: 1.0,
529 flops_per_second: 1e15,
530 };
531 assert!(stats.memory_bandwidth_utilization <= 1.0);
532 assert!(stats.compute_utilization <= 1.0);
533 assert!(stats.cache_hit_rate <= 1.0);
534 }
535
536 #[test]
537 fn test_gpu_memory_stats_zero_usage() {
538 let stats = GPUMemoryStats {
539 total_memory: 16 * 1024 * 1024 * 1024,
540 used_memory: 0,
541 available_memory: 16 * 1024 * 1024 * 1024,
542 optimizer_memory: 0,
543 };
544 assert_eq!(stats.used_memory, 0);
545 assert_eq!(stats.total_memory, stats.available_memory);
546 }
547
548 #[test]
549 fn test_gpu_memory_stats_full_usage() {
550 let total = 8 * 1024 * 1024 * 1024_usize;
551 let stats = GPUMemoryStats {
552 total_memory: total,
553 used_memory: total,
554 available_memory: 0,
555 optimizer_memory: total / 4,
556 };
557 assert_eq!(stats.available_memory, 0);
558 assert!(stats.optimizer_memory <= stats.used_memory);
559 }
560
561 #[test]
562 fn test_gpu_memory_stats_optimizer_fraction() {
563 let total = 16 * 1024 * 1024 * 1024_usize;
564 let used = 12 * 1024 * 1024 * 1024_usize;
565 let optimizer = 3 * 1024 * 1024 * 1024_usize;
566 let stats = GPUMemoryStats {
567 total_memory: total,
568 used_memory: used,
569 available_memory: total - used,
570 optimizer_memory: optimizer,
571 };
572 assert_eq!(stats.available_memory, 4 * 1024 * 1024 * 1024);
573 assert!(stats.optimizer_memory < stats.used_memory);
574 }
575
576 #[test]
577 fn test_hardware_stats_clone() {
578 let stats = HardwareStats {
579 memory_bandwidth_utilization: 0.5,
580 compute_utilization: 0.7,
581 cache_hit_rate: 0.9,
582 flops_per_second: 5e11,
583 };
584 let cloned = stats.clone();
585 assert_eq!(cloned.memory_bandwidth_utilization, 0.5);
586 assert_eq!(cloned.compute_utilization, 0.7);
587 }
588
589 #[test]
590 fn test_gpu_memory_stats_clone() {
591 let stats = GPUMemoryStats {
592 total_memory: 1000,
593 used_memory: 500,
594 available_memory: 500,
595 optimizer_memory: 100,
596 };
597 let cloned = stats.clone();
598 assert_eq!(cloned.total_memory, 1000);
599 }
600
601 #[test]
602 fn test_staleness_compensation_copy() {
603 let comp = StalenessCompensation::Linear;
604 let copied = comp;
605 assert!(matches!(copied, StalenessCompensation::Linear));
606 }
607
608 #[test]
609 fn test_hardware_stats_realistic_gpu() {
610 let stats = HardwareStats {
611 memory_bandwidth_utilization: 0.75,
612 compute_utilization: 0.85,
613 cache_hit_rate: 0.92,
614 flops_per_second: 1.2e13,
615 };
616 assert!(
617 stats.memory_bandwidth_utilization > 0.0 && stats.memory_bandwidth_utilization <= 1.0
618 );
619 assert!(stats.compute_utilization > 0.0 && stats.compute_utilization <= 1.0);
620 assert!(stats.flops_per_second > 1e12);
621 }
622
623 #[test]
624 fn test_hardware_stats_edge_device() {
625 let stats = HardwareStats {
626 memory_bandwidth_utilization: 0.3,
627 compute_utilization: 0.4,
628 cache_hit_rate: 0.6,
629 flops_per_second: 1e9,
630 };
631 assert!(stats.flops_per_second < 1e10);
632 assert!(stats.compute_utilization < 0.5);
633 }
634
635 #[test]
636 fn test_gpu_memory_stats_consistency() {
637 let stats = GPUMemoryStats {
638 total_memory: 8 * 1024 * 1024 * 1024,
639 used_memory: 6 * 1024 * 1024 * 1024,
640 available_memory: 2 * 1024 * 1024 * 1024,
641 optimizer_memory: 2 * 1024 * 1024 * 1024,
642 };
643 assert_eq!(
644 stats.used_memory + stats.available_memory,
645 stats.total_memory
646 );
647 }
648
649 #[test]
650 fn test_staleness_polynomial_fractional() {
651 let comp = StalenessCompensation::Polynomial(0.5);
652 if let StalenessCompensation::Polynomial(degree) = comp {
653 assert!(degree > 0.0 && degree < 1.0);
654 }
655 }
656
657 #[test]
658 fn test_staleness_polynomial_high_degree() {
659 let comp = StalenessCompensation::Polynomial(10.0);
660 if let StalenessCompensation::Polynomial(degree) = comp {
661 assert!(degree > 5.0);
662 }
663 }
664
665 #[test]
666 fn test_hardware_stats_debug_format() {
667 let stats = HardwareStats {
668 memory_bandwidth_utilization: 0.5,
669 compute_utilization: 0.5,
670 cache_hit_rate: 0.5,
671 flops_per_second: 1.0,
672 };
673 let debug_str = format!("{:?}", stats);
674 assert!(debug_str.contains("HardwareStats"));
675 }
676
677 #[test]
678 fn test_gpu_memory_stats_debug_format() {
679 let stats = GPUMemoryStats {
680 total_memory: 100,
681 used_memory: 50,
682 available_memory: 50,
683 optimizer_memory: 10,
684 };
685 let debug_str = format!("{:?}", stats);
686 assert!(debug_str.contains("GPUMemoryStats"));
687 }
688}