cuda_rust_wasm/neural_integration/
examples.rs

1//! Examples and Demos for Neural Integration
2//!
3//! This module provides comprehensive examples showing how to use the 
4//! CUDA-WASM neural integration with ruv-FANN.
5
6use super::{
7    ActivationFunction, BridgeConfig, NeuralBridge, NeuralOperation, NeuralResult,
8    GpuDevice, Precision,
9};
10
11/// Example: Basic matrix operations with GPU acceleration
12pub fn matrix_operations_example() -> NeuralResult<()> {
13    println!("=== Matrix Operations Example ===");
14    
15    // Create bridge with GPU acceleration
16    let config = BridgeConfig {
17        enable_gpu: true,
18        gpu_device: GpuDevice::Auto,
19        memory_pool_size: 256, // 256 MB
20        enable_monitoring: true,
21        auto_fallback: true,
22        batch_size: 32,
23        precision: Precision::Float32,
24    };
25    
26    let bridge = NeuralBridge::with_config(config)?;
27    
28    println!("GPU Available: {}", bridge.is_gpu_available());
29    if let Some(info) = bridge.get_device_info() {
30        println!("Device: {} ({})", info.name, info.vendor);
31    }
32    
33    // Example matrix multiplication: 4x4 * 4x4
34    let matrix_a = vec![
35        1.0, 2.0, 3.0, 4.0,
36        5.0, 6.0, 7.0, 8.0,
37        9.0, 10.0, 11.0, 12.0,
38        13.0, 14.0, 15.0, 16.0,
39    ];
40    
41    let matrix_b = vec![
42        1.0, 0.0, 0.0, 0.0,
43        0.0, 1.0, 0.0, 0.0,
44        0.0, 0.0, 1.0, 0.0,
45        0.0, 0.0, 0.0, 1.0,
46    ];
47    
48    let mut input_data = matrix_a.clone();
49    input_data.extend(matrix_b);
50    
51    let operation = NeuralOperation::MatrixMultiply {
52        a_rows: 4,
53        a_cols: 4,
54        b_cols: 4,
55        _phantom: std::marker::PhantomData,
56    };
57    
58    let result = bridge.execute_neural_operation(operation, &input_data)?;
59    
60    println!("Matrix A * Identity Matrix =");
61    for i in 0..4 {
62        for j in 0..4 {
63            print!("{:8.2} ", result[i * 4 + j]);
64        }
65        println!();
66    }
67    
68    let stats = bridge.get_performance_stats();
69    println!("Performance: {:.2} ops/sec", stats.throughput);
70    
71    Ok(())
72}
73
74/// Example: Neural network forward propagation
75pub fn neural_network_example() -> NeuralResult<()> {
76    println!("\n=== Neural Network Example ===");
77    
78    let bridge = NeuralBridge::new()?;
79    
80    // Create a simple neural network: 3 inputs -> 4 hidden -> 2 outputs
81    let layer_sizes = vec![3, 4, 2];
82    
83    // Sample input data
84    let input_data = vec![0.5, 0.8, 0.2]; // 3 inputs
85    
86    // Forward propagation
87    let operation = NeuralOperation::ForwardPropagation {
88        layer_sizes: layer_sizes.clone(),
89        _phantom: std::marker::PhantomData,
90    };
91    
92    let result = bridge.execute_neural_operation(operation, &input_data)?;
93    
94    println!("Network architecture: {layer_sizes:?}");
95    println!("Input: {input_data:?}");
96    println!("Output: {result:?}");
97    
98    // Test different activation functions
99    let activation_functions = [
100        ("Sigmoid", ActivationFunction::Sigmoid),
101        ("ReLU", ActivationFunction::ReLU),
102        ("Tanh", ActivationFunction::Tanh),
103        ("GELU", ActivationFunction::GELU),
104    ];
105    
106    let test_input = vec![-2.0, -1.0, 0.0, 1.0, 2.0];
107    
108    println!("\nActivation Function Comparison:");
109    for (name, function) in &activation_functions {
110        let operation = NeuralOperation::ActivationFunction {
111            function: *function,
112            size: test_input.len(),
113            _phantom: std::marker::PhantomData,
114        };
115        
116        let result = bridge.execute_neural_operation(operation, &test_input)?;
117        println!("{name:>8}: {result:?}");
118    }
119    
120    Ok(())
121}
122
123/// Example: Performance benchmarking
124pub fn performance_benchmark_example() -> NeuralResult<()> {
125    println!("\n=== Performance Benchmark Example ===");
126    
127    let bridge = NeuralBridge::new()?;
128    
129    // Benchmark different operation sizes
130    let sizes = vec![100, 1000, 10000, 100000];
131    
132    println!("Vector Addition Benchmark:");
133    for size in &sizes {
134        let a: Vec<f32> = (0..*size).map(|i| i as f32).collect();
135        let b: Vec<f32> = (0..*size).map(|i| (i * 2) as f32).collect();
136        
137        let mut input_data = a;
138        input_data.extend(b);
139        
140        let operation = NeuralOperation::VectorAdd { size: *size, _phantom: std::marker::PhantomData };
141        
142        let start = std::time::Instant::now();
143        let _result = bridge.execute_neural_operation(operation, &input_data)?;
144        let duration = start.elapsed();
145        
146        let throughput = *size as f64 / duration.as_secs_f64();
147        println!("  Size {size:6}: {throughput:8.2} elements/sec");
148    }
149    
150    // Matrix multiplication benchmark
151    println!("\nMatrix Multiplication Benchmark:");
152    let matrix_sizes = vec![16, 32, 64, 128];
153    
154    for size in &matrix_sizes {
155        let matrix_a: Vec<f32> = (0..size * size).map(|i| i as f32).collect();
156        let matrix_b: Vec<f32> = (0..size * size).map(|i| (i * 2) as f32).collect();
157        
158        let mut input_data = matrix_a;
159        input_data.extend(matrix_b);
160        
161        let operation = NeuralOperation::MatrixMultiply {
162            a_rows: *size,
163            a_cols: *size,
164            b_cols: *size,
165            _phantom: std::marker::PhantomData,
166        };
167        
168        let start = std::time::Instant::now();
169        let _result = bridge.execute_neural_operation(operation, &input_data)?;
170        let duration = start.elapsed();
171        
172        let flops = 2.0 * (*size as f64).powi(3); // 2 * n^3 operations
173        let gflops = flops / duration.as_secs_f64() / 1e9;
174        
175        println!("  {size}x{size}: {gflops:8.2} GFLOPS");
176    }
177    
178    let memory_stats = bridge.get_memory_stats();
179    println!("\nMemory Usage:");
180    println!("  Total: {} bytes", memory_stats.total_allocated);
181    println!("  GPU: {} bytes", memory_stats.gpu_allocated);
182    println!("  CPU: {} bytes", memory_stats.cpu_allocated);
183    
184    Ok(())
185}
186
187/// Example: Batch processing for efficiency
188pub fn batch_processing_example() -> NeuralResult<()> {
189    println!("\n=== Batch Processing Example ===");
190    
191    let bridge = NeuralBridge::new()?;
192    let batch_processor = bridge.create_batch_processor();
193    
194    // Create multiple operations to process in batch
195    let operations = vec![
196        NeuralOperation::VectorAdd { size: 1000, _phantom: std::marker::PhantomData },
197        NeuralOperation::ActivationFunction { 
198            function: ActivationFunction::ReLU, 
199            size: 1000,
200            _phantom: std::marker::PhantomData 
201        },
202        NeuralOperation::ActivationFunction { 
203            function: ActivationFunction::Sigmoid, 
204            size: 1000,
205            _phantom: std::marker::PhantomData 
206        },
207    ];
208    
209    let inputs = vec![
210        // Vector addition input (a + b)
211        {
212            let mut data: Vec<f32> = (0..1000).map(|i| i as f32).collect();
213            data.extend((0..1000).map(|i| (i * 2) as f32));
214            data
215        },
216        // ReLU input
217        (0..1000).map(|i| (i as f32) - 500.0).collect(),
218        // Sigmoid input
219        (0..1000).map(|i| (i as f32) / 100.0 - 5.0).collect(),
220    ];
221    
222    let start = std::time::Instant::now();
223    let results = batch_processor.process_batch(operations, inputs)?;
224    let duration = start.elapsed();
225    
226    println!("Processed {} operations in {:.2}ms", results.len(), duration.as_millis());
227    println!("Batch throughput: {:.2} ops/sec", results.len() as f64 / duration.as_secs_f64());
228    
229    // Show some results
230    for (i, result) in results.iter().enumerate() {
231        println!("Operation {}: {} outputs", i, result.len());
232        if !result.is_empty() {
233            println!("  First 5: {:?}", &result[0..5.min(result.len())]);
234        }
235    }
236    
237    Ok(())
238}
239
240/// Example: Custom CUDA kernel integration
241pub fn custom_kernel_example() -> NeuralResult<()> {
242    println!("\n=== Custom CUDA Kernel Example ===");
243    
244    let bridge = NeuralBridge::new()?;
245    
246    // Custom CUDA kernel for element-wise square
247    let kernel_source = r#"
248        __global__ void element_square(float* input, float* output, int size) {
249            int idx = blockIdx.x * blockDim.x + threadIdx.x;
250            if (idx < size) {
251                output[idx] = input[idx] * input[idx];
252            }
253        }
254    "#;
255    
256    let input_data: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0, 5.0];
257    
258    let operation = NeuralOperation::Custom {
259        kernel_source: kernel_source.to_string(),
260        name: "element_square".to_string(),
261        _phantom: std::marker::PhantomData,
262    };
263    
264    let result = bridge.execute_neural_operation(operation, &input_data)?;
265    
266    println!("Custom Kernel: Element-wise Square");
267    println!("Input:  {input_data:?}");
268    println!("Output: {result:?}");
269    
270    // Verify results
271    let expected: Vec<f32> = input_data.iter().map(|x| x * x).collect();
272    println!("Expected: {expected:?}");
273    
274    Ok(())
275}
276
277/// Example: Error handling and fallback behavior
278pub fn error_handling_example() -> NeuralResult<()> {
279    println!("\n=== Error Handling Example ===");
280    
281    // Test with GPU disabled to demonstrate fallback
282    let config = BridgeConfig {
283        enable_gpu: false, // Force CPU mode
284        auto_fallback: true,
285        ..Default::default()
286    };
287    
288    let bridge = NeuralBridge::with_config(config)?;
289    
290    println!("GPU Available: {} (forced CPU mode)", bridge.is_gpu_available());
291    
292    // This should work even without GPU
293    let operation = NeuralOperation::VectorAdd { size: 100, _phantom: std::marker::PhantomData };
294    let input_data: Vec<f32> = (0..200).map(|i| i as f32).collect();
295    
296    match bridge.execute_neural_operation(operation, &input_data) {
297        Ok(result) => {
298            println!("CPU fallback successful: {} results", result.len());
299            println!("First 5 results: {:?}", &result[0..5]);
300        }
301        Err(e) => {
302            println!("Error: {e}");
303        }
304    }
305    
306    // Test error conditions
307    println!("\nTesting error conditions:");
308    
309    // Invalid input size
310    let operation = NeuralOperation::VectorAdd { size: 100, _phantom: std::marker::PhantomData };
311    let invalid_input = vec![1.0, 2.0, 3.0]; // Too small
312    
313    match bridge.execute_neural_operation(operation, &invalid_input) {
314        Ok(_) => println!("Unexpected success with invalid input"),
315        Err(e) => println!("Expected error: {e}"),
316    }
317    
318    Ok(())
319}
320
321/// Example: Real-world neural network training simulation
322pub fn training_simulation_example() -> NeuralResult<()> {
323    println!("\n=== Training Simulation Example ===");
324    
325    let bridge = NeuralBridge::new()?;
326    
327    // Simulate training a simple neural network
328    let layer_sizes = vec![4, 8, 8, 3]; // 4 inputs, 2 hidden layers, 3 outputs
329    let learning_rate = 0.01;
330    let epochs = 100;
331    
332    println!("Neural Network: {layer_sizes:?}");
333    println!("Learning Rate: {learning_rate}");
334    println!("Epochs: {epochs}");
335    
336    // Generate synthetic training data
337    let batch_size = 32;
338    let training_samples = 1000;
339    
340    println!("\nSimulating training...");
341    
342    for epoch in 0..epochs {
343        let mut total_loss = 0.0;
344        
345        for batch in 0..(training_samples / batch_size) {
346            // Generate random batch
347            let batch_input: Vec<f32> = (0..batch_size * layer_sizes[0])
348                .map(|_| rand::random::<f32>() * 2.0 - 1.0)
349                .collect();
350            
351            // Forward propagation
352            let forward_op = NeuralOperation::ForwardPropagation {
353                layer_sizes: layer_sizes.clone(),
354                _phantom: std::marker::PhantomData,
355            };
356            
357            let _outputs = bridge.execute_neural_operation(forward_op, &batch_input)?;
358            
359            // Simulate loss calculation
360            let loss = rand::random::<f32>() * 0.1 + 0.9_f32.powf(epoch as f32);
361            total_loss += loss;
362            
363            // Backward propagation (simulated)
364            let backward_op = NeuralOperation::BackwardPropagation {
365                layer_sizes: layer_sizes.clone(),
366                _phantom: std::marker::PhantomData,
367            };
368            
369            let _gradients = bridge.execute_neural_operation(backward_op, &batch_input)?;
370        }
371        
372        let avg_loss = total_loss / (training_samples / batch_size) as f32;
373        
374        if epoch % 20 == 0 {
375            println!("Epoch {epoch}: Loss = {avg_loss:.6}");
376        }
377    }
378    
379    let perf_stats = bridge.get_performance_stats();
380    println!("\nTraining completed!");
381    println!("Total operations: {}", perf_stats.total_operations);
382    println!("Average execution time: {:.2}ms", perf_stats.average_execution_time * 1000.0);
383    println!("GPU utilization: {:.1}%", perf_stats.gpu_utilization * 100.0);
384    
385    Ok(())
386}
387
388/// Run all examples
389pub fn run_all_examples() -> NeuralResult<()> {
390    println!("CUDA-WASM Neural Integration Examples");
391    println!("=====================================");
392    
393    matrix_operations_example()?;
394    neural_network_example()?;
395    performance_benchmark_example()?;
396    batch_processing_example()?;
397    custom_kernel_example()?;
398    error_handling_example()?;
399    training_simulation_example()?;
400    
401    println!("\n=== All Examples Completed Successfully! ===");
402    
403    Ok(())
404}
405
406#[cfg(test)]
407mod tests {
408    use super::*;
409    
410    #[test]
411    fn test_matrix_operations_example() {
412        let result = matrix_operations_example();
413        assert!(result.is_ok(), "Matrix operations example failed: {result:?}");
414    }
415    
416    #[test]
417    fn test_neural_network_example() {
418        let result = neural_network_example();
419        assert!(result.is_ok(), "Neural network example failed: {result:?}");
420    }
421    
422    #[test]
423    fn test_error_handling_example() {
424        let result = error_handling_example();
425        assert!(result.is_ok(), "Error handling example failed: {result:?}");
426    }
427}