Files
rustytorch/crates/training/rtx-transformers/src/revolutionary/edge_deployment.rs
T
osobhandClaude Opus 4.6 02d382d5f6 style: apply rustfmt across all crates and demos
Consistent formatting pass: line wrapping, import sorting, trailing
whitespace removal, let-chain indentation, merged derive attributes,
and unsafe block reformatting.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
2026-04-12 07:01:58 -07:00

582 lines
21 KiB
Rust

//! Edge deployment validation and cross-platform compatibility
//!
//! This module provides deployment validation and compatibility checking for:
//! - ARM, RISC-V, WebAssembly, mobile GPU, and `IoT` platforms
//! - Memory and compute requirement estimation
//! - Performance prediction and validation
//! - Cross-platform deployment optimization
use crate::Result;
use crate::revolutionary::EdgeTarget;
use crate::revolutionary::edge_capabilities::EdgeCapabilities;
use std::collections::HashMap;
use std::time::Duration;
/// Deployment validation result for specific target
#[derive(Debug, Clone)]
pub struct DeploymentValidation {
pub compatible: bool,
pub memory_requirement_mb: u64,
pub compute_requirement: f32,
pub estimated_performance: PerformanceEstimate,
pub validation_time: Duration,
pub issues: Vec<String>,
}
/// Performance estimation for target platform
#[derive(Debug, Clone)]
pub struct PerformanceEstimate {
pub throughput_tokens_per_sec: f32,
pub latency_ms: f32,
pub memory_bandwidth_gb_s: f32,
pub power_efficiency_tokens_per_watt: f32,
}
/// Edge deployment validator
#[derive(Debug)]
pub struct EdgeDeploymentValidator {
capabilities: EdgeCapabilities,
}
impl EdgeDeploymentValidator {
#[must_use]
pub fn new(capabilities: EdgeCapabilities) -> Self {
Self { capabilities }
}
pub fn validate_deployment(
&self,
targets: &[EdgeTarget],
) -> Result<HashMap<EdgeTarget, DeploymentValidation>> {
let mut validation = HashMap::new();
for target in targets {
let validation_result = self.validate_target_compatibility(target)?;
validation.insert(target.clone(), validation_result);
}
Ok(validation)
}
fn validate_target_compatibility(&self, target: &EdgeTarget) -> Result<DeploymentValidation> {
let start_time = std::time::Instant::now();
let compatibility_checks = match target {
EdgeTarget::ARM => self.validate_arm_compatibility(),
EdgeTarget::RISCV => self.validate_riscv_compatibility(),
EdgeTarget::WASM => self.validate_wasm_compatibility(),
EdgeTarget::Mobile => self.validate_mobile_compatibility(),
EdgeTarget::MobileGPU => self.validate_mobile_gpu_compatibility(),
EdgeTarget::FPGA => self.validate_fpga_compatibility(),
EdgeTarget::IoT => self.validate_iot_compatibility(),
EdgeTarget::Embedded => self.validate_embedded_compatibility(),
EdgeTarget::Custom(name) => self.validate_custom_compatibility(name),
};
let validation_time = start_time.elapsed();
Ok(DeploymentValidation {
compatible: compatibility_checks.is_ok(),
memory_requirement_mb: self.estimate_memory_requirement(target),
compute_requirement: self.estimate_compute_requirement(target),
estimated_performance: self.estimate_performance(target),
validation_time,
issues: if compatibility_checks.is_err() {
vec![format!(
"Compatibility issue: {:?}",
compatibility_checks.unwrap_err()
)]
} else {
vec![]
},
})
}
/// Validate ARM platform compatibility
/// Requires: NEON SIMD support, minimum 512MB RAM, at least 2 compute units
fn validate_arm_compatibility(&self) -> Result<()> {
use crate::revolutionary::edge_capabilities::SIMDClass;
// ARM requires NEON SIMD for efficient inference
if !matches!(
self.capabilities.simd_support,
SIMDClass::NEON | SIMDClass::AVX
) {
return Err(crate::TransformerError::Generic(
"ARM deployment requires NEON SIMD support".into(),
));
}
// Minimum memory requirement for ARM deployment
if self.capabilities.memory_mb < 512 {
return Err(crate::TransformerError::Generic(format!(
"ARM deployment requires at least 512MB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// Need at least 2 compute units for efficient ARM inference
if self.capabilities.compute_units < 2 {
return Err(crate::TransformerError::Generic(
"ARM deployment requires at least 2 compute units".into(),
));
}
Ok(())
}
/// Validate RISC-V platform compatibility
/// Requires: RVV (RISC-V Vector) support preferred, minimum 256MB RAM
fn validate_riscv_compatibility(&self) -> Result<()> {
// RISC-V works best with RVV, but can fallback to scalar
// We just warn if no vector support
if self.capabilities.memory_mb < 256 {
return Err(crate::TransformerError::Generic(format!(
"RISC-V deployment requires at least 256MB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// RISC-V is still emerging - lower compute requirements
if self.capabilities.compute_units < 1 {
return Err(crate::TransformerError::Generic(
"RISC-V deployment requires at least 1 compute unit".into(),
));
}
Ok(())
}
/// Validate WebAssembly platform compatibility
/// Requires: WASM SIMD support for performance, memory limits apply
fn validate_wasm_compatibility(&self) -> Result<()> {
use crate::revolutionary::edge_capabilities::SIMDClass;
// WASM has a 4GB memory limit per module in practice
if self.capabilities.memory_mb > 4096 {
// This is actually fine, we just won't use all of it
}
// WASM requires at least 128MB for model + runtime
if self.capabilities.memory_mb < 128 {
return Err(crate::TransformerError::Generic(format!(
"WASM deployment requires at least 128MB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// WASM SIMD significantly improves performance
if !matches!(
self.capabilities.simd_support,
SIMDClass::WASM_SIMD | SIMDClass::AVX | SIMDClass::NEON
) {
// Not an error, but performance will be degraded
tracing::warn!("WASM deployment without SIMD will have reduced performance");
}
Ok(())
}
/// Validate mobile platform compatibility
/// Balanced requirements for smartphone deployment
fn validate_mobile_compatibility(&self) -> Result<()> {
use crate::revolutionary::edge_capabilities::{EdgeClass, PowerClass};
// Mobile requires at least mid-tier device capabilities
if matches!(self.capabilities.edge_class, EdgeClass::IoT) {
return Err(crate::TransformerError::Generic(
"Mobile deployment not suitable for IoT-class devices".into(),
));
}
// Mobile deployment needs reasonable memory
if self.capabilities.memory_mb < 1024 {
return Err(crate::TransformerError::Generic(format!(
"Mobile deployment requires at least 1GB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// Power budget should support at least standard battery operation
if matches!(self.capabilities.power_budget, PowerClass::UltraLowPower) {
return Err(crate::TransformerError::Generic(
"Mobile deployment requires at least low power budget".into(),
));
}
Ok(())
}
/// Validate mobile GPU platform compatibility
/// Requires GPU compute capabilities on mobile devices
fn validate_mobile_gpu_compatibility(&self) -> Result<()> {
// Mobile GPU requires more memory for GPU buffers
if self.capabilities.memory_mb < 2048 {
return Err(crate::TransformerError::Generic(format!(
"Mobile GPU deployment requires at least 2GB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// GPU deployment needs multiple compute units
if self.capabilities.compute_units < 4 {
return Err(crate::TransformerError::Generic(
"Mobile GPU deployment requires at least 4 compute units".into(),
));
}
// High-end or mid-tier devices only
use crate::revolutionary::edge_capabilities::EdgeClass;
if matches!(
self.capabilities.edge_class,
EdgeClass::Low | EdgeClass::IoT
) {
return Err(crate::TransformerError::Generic(
"Mobile GPU deployment requires mid-tier or high-end device".into(),
));
}
Ok(())
}
/// Validate FPGA platform compatibility
/// Specialized requirements for FPGA acceleration
fn validate_fpga_compatibility(&self) -> Result<()> {
// FPGA requires significant memory for bitstream and buffers
if self.capabilities.memory_mb < 4096 {
return Err(crate::TransformerError::Generic(format!(
"FPGA deployment requires at least 4GB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// FPGA typically has wall power
use crate::revolutionary::edge_capabilities::PowerClass;
if matches!(
self.capabilities.power_budget,
PowerClass::LowPower | PowerClass::UltraLowPower
) {
return Err(crate::TransformerError::Generic(
"FPGA deployment requires at least standard battery power budget".into(),
));
}
// Check for FPGA-specific optimization flags
if !self
.capabilities
.optimization_flags
.contains_key("fpga_bitstream")
{
tracing::warn!("FPGA deployment: no bitstream optimization flag set");
}
Ok(())
}
/// Validate `IoT` platform compatibility
/// Ultra-constrained resource requirements
fn validate_iot_compatibility(&self) -> Result<()> {
// IoT deployment is for constrained devices
// Very minimal requirements - just need to fit in limited memory
if self.capabilities.memory_mb < 32 {
return Err(crate::TransformerError::Generic(format!(
"IoT deployment requires at least 32MB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// IoT doesn't require SIMD - scalar is acceptable
// IoT doesn't require multiple compute units
Ok(())
}
/// Validate embedded platform compatibility
/// Requirements for embedded Linux/RTOS systems
fn validate_embedded_compatibility(&self) -> Result<()> {
// Embedded systems need modest memory
if self.capabilities.memory_mb < 64 {
return Err(crate::TransformerError::Generic(format!(
"Embedded deployment requires at least 64MB RAM, got {}MB",
self.capabilities.memory_mb
)));
}
// At least 1 compute unit required
if self.capabilities.compute_units < 1 {
return Err(crate::TransformerError::Generic(
"Embedded deployment requires at least 1 compute unit".into(),
));
}
Ok(())
}
/// Validate custom platform compatibility
/// Checks for platform-specific optimization flags
fn validate_custom_compatibility(&self, name: &str) -> Result<()> {
// Check if custom platform has required configuration
let platform_key = format!("custom_{name}");
if !self
.capabilities
.optimization_flags
.contains_key(&platform_key)
{
tracing::warn!(
"Custom platform '{}' has no specific optimization flags configured",
name
);
}
// Basic sanity check - need at least some resources
if self.capabilities.memory_mb < 16 {
return Err(crate::TransformerError::Generic(format!(
"Custom platform '{name}' requires at least 16MB RAM"
)));
}
Ok(())
}
/// Estimate memory requirement in MB for target platform
fn estimate_memory_requirement(&self, target: &EdgeTarget) -> u64 {
// Base memory for model weights (assuming quantized model)
let base_model_memory: u64 = 256; // MB for a small quantized model
// Platform-specific overhead multipliers
let overhead_multiplier = match target {
EdgeTarget::ARM => 1.5, // Runtime + NEON buffers
EdgeTarget::RISCV => 1.3, // Smaller runtime
EdgeTarget::WASM => 2.0, // JavaScript runtime + linear memory
EdgeTarget::Mobile => 1.8, // OS overhead + app framework
EdgeTarget::MobileGPU => 2.5, // GPU memory + CPU copy
EdgeTarget::FPGA => 3.0, // Bitstream + double buffering
EdgeTarget::IoT => 1.1, // Minimal overhead
EdgeTarget::Embedded => 1.2, // Small RTOS overhead
EdgeTarget::Custom(_) => 1.5, // Conservative estimate
};
// Scale by available compute (more compute = can handle larger models)
let compute_factor = (f64::from(self.capabilities.compute_units) / 4.0)
.min(2.0)
.max(0.5);
let estimated = (base_model_memory as f64 * overhead_multiplier * compute_factor) as u64;
// Ensure we don't exceed available memory
estimated.min(self.capabilities.memory_mb)
}
/// Estimate compute requirement as normalized score (0-10)
fn estimate_compute_requirement(&self, target: &EdgeTarget) -> f32 {
use crate::revolutionary::edge_capabilities::SIMDClass;
// Base compute score (higher = more demanding)
let base_score = match target {
EdgeTarget::ARM => 3.0,
EdgeTarget::RISCV => 4.0, // Less mature tooling
EdgeTarget::WASM => 5.0, // Interpreted overhead
EdgeTarget::Mobile => 3.5,
EdgeTarget::MobileGPU => 2.0, // GPU offload helps
EdgeTarget::FPGA => 1.5, // Hardware acceleration
EdgeTarget::IoT => 6.0, // Very constrained
EdgeTarget::Embedded => 5.0,
EdgeTarget::Custom(_) => 4.0,
};
// Adjust based on SIMD support
let simd_factor = match self.capabilities.simd_support {
SIMDClass::AVX => 0.6, // Best - AVX-512/AVX2
SIMDClass::NEON => 0.7, // Good - ARM NEON
SIMDClass::WASM_SIMD => 0.8, // Decent - WASM SIMD
SIMDClass::RVV => 0.75, // Good when available
SIMDClass::None => 1.0, // No acceleration
};
// Adjust based on compute units
let compute_factor = 1.0 / (1.0 + (self.capabilities.compute_units as f32 - 1.0) * 0.1);
(base_score * simd_factor * compute_factor).min(10.0)
}
/// Estimate performance characteristics for target platform
fn estimate_performance(&self, target: &EdgeTarget) -> PerformanceEstimate {
use crate::revolutionary::edge_capabilities::{EdgeClass, PowerClass, SIMDClass};
// Base throughput (tokens/sec) for a reference model
let base_throughput = match target {
EdgeTarget::ARM => 50.0,
EdgeTarget::RISCV => 30.0,
EdgeTarget::WASM => 25.0,
EdgeTarget::Mobile => 40.0,
EdgeTarget::MobileGPU => 150.0,
EdgeTarget::FPGA => 200.0,
EdgeTarget::IoT => 5.0,
EdgeTarget::Embedded => 15.0,
EdgeTarget::Custom(_) => 30.0,
};
// Scale by compute units
let compute_scale = (self.capabilities.compute_units as f32).sqrt();
// Scale by SIMD capability
let simd_scale: f32 = match self.capabilities.simd_support {
SIMDClass::AVX => 4.0,
SIMDClass::NEON => 3.0,
SIMDClass::WASM_SIMD => 2.0,
SIMDClass::RVV => 2.5,
SIMDClass::None => 1.0,
};
// Scale by device class
let class_scale = match self.capabilities.edge_class {
EdgeClass::HighEnd => 2.0,
EdgeClass::Mid => 1.0,
EdgeClass::Low => 0.5,
EdgeClass::IoT => 0.2,
};
let throughput = base_throughput * compute_scale * simd_scale.sqrt() * class_scale;
// Latency is inverse of throughput with some fixed overhead
let fixed_overhead_ms = match target {
EdgeTarget::WASM => 5.0, // JS interop overhead
EdgeTarget::FPGA => 2.0, // Programming overhead
EdgeTarget::IoT => 10.0, // Slow memory
_ => 1.0,
};
let latency = fixed_overhead_ms + (1000.0 / throughput);
// Memory bandwidth estimate (GB/s)
let memory_bandwidth = match target {
EdgeTarget::MobileGPU => 50.0,
EdgeTarget::FPGA => 100.0,
EdgeTarget::ARM => 25.0,
EdgeTarget::Mobile => 20.0,
EdgeTarget::WASM => 10.0,
EdgeTarget::IoT => 2.0,
EdgeTarget::Embedded => 5.0,
_ => 15.0,
} * (self.capabilities.memory_mb as f32 / 2048.0)
.sqrt()
.min(2.0);
// Power efficiency (tokens per watt)
let base_efficiency = match self.capabilities.power_budget {
PowerClass::Unlimited => 100.0, // Doesn't care about power
PowerClass::HighBattery => 500.0,
PowerClass::StandardBattery => 1000.0,
PowerClass::LowPower => 2000.0,
PowerClass::UltraLowPower => 5000.0, // Very efficient
};
// Adjust efficiency by throughput
let power_efficiency = base_efficiency * (throughput / 100.0).sqrt();
PerformanceEstimate {
throughput_tokens_per_sec: throughput,
latency_ms: latency,
memory_bandwidth_gb_s: memory_bandwidth,
power_efficiency_tokens_per_watt: power_efficiency,
}
}
}
#[cfg(all(test, feature = "disabled_tests"))]
mod tests {
use super::*;
use crate::revolutionary::edge_capabilities::{
EdgeCapabilityDetector, EdgeClass, NetworkClass, PowerClass, SIMDClass,
};
fn create_test_capabilities() -> EdgeCapabilities {
EdgeCapabilities {
compute_units: 4,
memory_mb: 2048,
simd_support: SIMDClass::NEON,
power_budget: PowerClass::StandardBattery,
network: NetworkClass::WiFi,
edge_class: EdgeClass::Mid,
optimization_flags: HashMap::new(),
}
}
#[test]
fn test_deployment_validator_creation() {
let capabilities = create_test_capabilities();
let validator = EdgeDeploymentValidator::new(capabilities);
assert_eq!(validator.capabilities.compute_units, 4);
}
#[test]
fn test_deployment_validation() {
let capabilities = create_test_capabilities();
let validator = EdgeDeploymentValidator::new(capabilities);
let targets = vec![EdgeTarget::ARM, EdgeTarget::WASM];
let validation = validator.validate_deployment(&targets).unwrap();
assert_eq!(validation.len(), 2);
assert!(validation.contains_key(&EdgeTarget::ARM));
assert!(validation.contains_key(&EdgeTarget::WASM));
}
#[test]
fn test_validation_structure() {
let validation = DeploymentValidation {
compatible: true,
memory_requirement_mb: 1024,
compute_requirement: 1.0,
estimated_performance: PerformanceEstimate {
throughput_tokens_per_sec: 100.0,
latency_ms: 10.0,
memory_bandwidth_gb_s: 25.0,
power_efficiency_tokens_per_watt: 1000.0,
},
validation_time: Duration::from_millis(100),
issues: vec![],
};
assert!(validation.compatible);
assert_eq!(validation.memory_requirement_mb, 1024);
assert_eq!(
validation.estimated_performance.throughput_tokens_per_sec,
100.0
);
}
#[test]
fn test_performance_estimate() {
let estimate = PerformanceEstimate {
throughput_tokens_per_sec: 150.0,
latency_ms: 6.67,
memory_bandwidth_gb_s: 30.0,
power_efficiency_tokens_per_watt: 1500.0,
};
assert_eq!(estimate.throughput_tokens_per_sec, 150.0);
assert_eq!(estimate.latency_ms, 6.67);
assert_eq!(estimate.memory_bandwidth_gb_s, 30.0);
assert_eq!(estimate.power_efficiency_tokens_per_watt, 1500.0);
}
#[test]
fn test_all_target_compatibility() {
let capabilities = create_test_capabilities();
let validator = EdgeDeploymentValidator::new(capabilities);
let all_targets = vec![
EdgeTarget::ARM,
EdgeTarget::RISCV,
EdgeTarget::WASM,
EdgeTarget::MobileGPU,
EdgeTarget::IoT,
EdgeTarget::Embedded,
];
let validation = validator.validate_deployment(&all_targets).unwrap();
assert_eq!(validation.len(), all_targets.len());
for target in &all_targets {
let result = validation.get(target).unwrap();
assert!(result.memory_requirement_mb > 0);
assert!(result.compute_requirement > 0.0);
assert!(result.validation_time.as_millis() >= 0);
}
}
}