1use crate::q_hash;
7use std::collections::HashMap;
8use std::fs::OpenOptions;
9#[cfg(unix)]
10use std::os::unix::io::AsRawFd;
11
12use serde::{Deserialize, Serialize};
13use std::path::Path;
14
15pub struct CsdManager {
17 devices: HashMap<String, CsdDevice>,
18 functions: HashMap<String, CsdFunction>,
19 scheduler: CsdScheduler,
20 performance_monitor: CsdPerformanceMonitor,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq)]
25pub struct CsdDeviceHandle {
26 pub device_id_hash: u64,
27 pub max_concurrent_operations: u32,
28 pub max_data_size: u64,
29 pub memory_size: u64,
30 pub compute_units: u32,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq)]
35pub struct CsdFunctionHandle {
36 pub function_id_hash: u64,
37 pub operation_tag: u8,
38 pub parameter_count: u16,
39 pub bytecode_len: u32,
40}
41
42#[derive(Debug, Clone)]
44pub struct CsdDevice {
45 pub device_id: String,
46 pub device_path: String,
47 pub capabilities: CsdCapabilities,
48 pub supported_functions: Vec<String>,
49 pub device_stats: CsdDeviceStats,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct CsdCapabilities {
55 pub max_concurrent_operations: u32,
56 pub max_data_size: u64,
57 pub supported_operations: Vec<CsdOperationType>,
58 pub memory_size: u64,
59 pub compute_units: u32,
60 pub clock_speed: f64,
61}
62
63#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
65pub enum CsdOperationType {
66 MatrixMultiply,
67 VectorDotProduct,
68 Convolution,
69 Filter,
70 Aggregate,
71 Sort,
72 Search,
73 Custom(String),
74}
75
76#[derive(Debug, Clone)]
78pub struct CsdFunction {
79 pub function_id: String,
80 pub operation: CsdOperationType,
81 pub parameters: Vec<FunctionParameter>,
82 pub bytecode: Vec<u8>,
83 pub performance_profile: PerformanceProfile,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct FunctionParameter {
89 pub name: String,
90 pub param_type: ParameterType,
91 pub size: u64,
92 pub is_input: bool,
93 pub is_output: bool,
94}
95
96#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98pub enum ParameterType {
99 Matrix,
100 Vector,
101 Scalar,
102 Tensor,
103 Buffer,
104}
105
106#[derive(Debug, Clone)]
108pub struct PerformanceProfile {
109 pub expected_execution_time: f64,
110 pub memory_usage: u64,
111 pub compute_intensity: f64,
112 pub data_intensity: f64,
113}
114
115#[derive(Debug, Clone)]
117pub struct CsdDeviceStats {
118 pub operations_completed: u64,
119 pub total_execution_time: u64,
120 pub average_execution_time: f64,
121 pub data_processed: u64,
122 pub error_count: u64,
123 pub utilization: f64,
124}
125
126pub struct CsdScheduler {
128 pending_operations: Vec<CsdOperationRequest>,
129 running_operations: HashMap<u64, CsdRunningOperation>,
130 completion_queue: Vec<CsdCompletion>,
131 scheduling_policy: SchedulingPolicy,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct CsdOperationRequest {
137 pub operation_id: u64,
138 pub function_id: String,
139 pub device_id: String,
140 pub inputs: Vec<OperationInput>,
141 pub outputs: Vec<OperationOutput>,
142 pub priority: OperationPriority,
143 pub deadline: Option<u64>,
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct OperationInput {
149 pub name: String,
150 pub data: Vec<u8>,
151 pub location: DataLocation,
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct OperationOutput {
157 pub name: String,
158 pub size: u64,
159 pub location: DataLocation,
160}
161
162#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
164pub enum DataLocation {
165 HostMemory,
166 DeviceMemory,
167 PersistentStorage,
168}
169
170#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
172pub enum OperationPriority {
173 Low,
174 Normal,
175 High,
176 Critical,
177}
178
179#[derive(Debug, Clone)]
181pub struct CsdRunningOperation {
182 pub operation_id: u64,
183 pub device_id: String,
184 pub start_time: u64,
185 pub progress: f64,
186}
187
188#[derive(Debug, Clone)]
190pub struct CsdCompletion {
191 pub operation_id: u64,
192 pub status: CompletionStatus,
193 pub execution_time: u64,
194 pub outputs: Vec<OperationOutput>,
195 pub error_message: Option<String>,
196}
197
198#[derive(Debug, Clone, PartialEq)]
200pub enum CompletionStatus {
201 Success,
202 Error,
203 Timeout,
204 Cancelled,
205}
206
207#[derive(Debug, Clone)]
209pub enum SchedulingPolicy {
210 Fifo,
212 Priority,
214 ShortestJobFirst,
216 Deadline,
218 LoadBalanced,
220}
221
222pub struct CsdPerformanceMonitor {
224 device_metrics: HashMap<String, CsdDeviceMetrics>,
225 function_metrics: HashMap<String, CsdFunctionMetrics>,
226 global_metrics: CsdGlobalMetrics,
227}
228
229#[derive(Debug, Clone)]
231pub struct CsdDeviceMetrics {
232 pub device_id: String,
233 pub utilization: f64,
234 pub throughput: f64,
235 pub latency: f64,
236 pub error_rate: f64,
237 pub power_consumption: f64,
238}
239
240#[derive(Debug, Clone)]
242pub struct CsdFunctionMetrics {
243 pub function_id: String,
244 pub execution_count: u64,
245 pub total_execution_time: u64,
246 pub average_execution_time: f64,
247 pub success_rate: f64,
248 pub data_throughput: f64,
249}
250
251#[derive(Debug, Clone)]
253pub struct CsdGlobalMetrics {
254 pub total_operations: u64,
255 pub total_execution_time: u64,
256 pub average_execution_time: f64,
257 pub total_data_processed: u64,
258 pub overall_throughput: f64,
259 pub system_utilization: f64,
260}
261
262pub struct MathComputationBuilder {
264 operations: Vec<CsdOperationRequest>,
265 data_dependencies: HashMap<String, Vec<String>>,
266 execution_plan: ExecutionPlan,
267}
268
269#[derive(Debug, Clone)]
271pub struct ExecutionPlan {
272 pub stages: Vec<ExecutionStage>,
273 pub parallel_groups: Vec<Vec<String>>,
274 pub estimated_time: f64,
275 pub resource_requirements: ResourceRequirements,
276}
277
278#[derive(Debug, Clone)]
280pub struct ExecutionStage {
281 pub stage_id: u32,
282 pub operations: Vec<String>,
283 pub dependencies: Vec<String>,
284 pub estimated_time: f64,
285}
286
287#[derive(Debug, Clone)]
289pub struct ResourceRequirements {
290 pub memory_usage: u64,
291 pub compute_units: u32,
292 pub bandwidth: f64,
293}
294
295impl CsdManager {
296 pub fn new() -> Self {
298 Self {
299 devices: HashMap::new(),
300 functions: HashMap::new(),
301 scheduler: CsdScheduler::new(),
302 performance_monitor: CsdPerformanceMonitor::new(),
303 }
304 }
305
306 pub fn register_device(&mut self, device: CsdDevice) -> Result<(), CsdError> {
307 self.devices.insert(device.device_id.clone(), device);
308 Ok(())
309 }
310
311 pub fn discover_devices(&mut self) -> Result<Vec<String>, CsdError> {
313 let mut discovered_devices = Vec::new();
314
315 for i in 0..16 {
317 let device_path = format!("/dev/nvme{}", i);
318 if Path::new(&device_path).exists() {
319 if let Ok(device) = self.probe_device(&device_path) {
320 discovered_devices.push(device.device_id.clone());
321 self.devices.insert(device.device_id.clone(), device);
322 }
323 }
324 }
325
326 Ok(discovered_devices)
327 }
328
329 pub fn discover_devices_into(
331 &mut self,
332 out: &mut [CsdDeviceHandle],
333 ) -> Result<usize, CsdError> {
334 let mut written = 0;
335
336 for i in 0..16 {
337 let device_path = format!("/dev/nvme{}", i);
338 if Path::new(&device_path).exists() {
339 if let Ok(device) = self.probe_device(&device_path) {
340 if written >= out.len() {
341 return Err(CsdError::BufferTooSmall(
342 "device discovery output buffer exhausted".to_string(),
343 ));
344 }
345 out[written] = Self::device_handle(&device);
346 written += 1;
347 self.devices.insert(device.device_id.clone(), device);
348 }
349 }
350 }
351
352 Ok(written)
353 }
354
355 fn probe_device(&self, device_path: &str) -> Result<CsdDevice, CsdError> {
357 let _device_file = OpenOptions::new()
358 .read(true)
359 .write(true)
360 .open(device_path)
361 .map_err(|e| CsdError::DeviceOpen(e.to_string()))?;
362
363 let device_id = format!("csd-{}", device_path);
365
366 let capabilities = CsdCapabilities {
368 max_concurrent_operations: 16,
369 max_data_size: 1024 * 1024 * 1024, supported_operations: vec![
371 CsdOperationType::MatrixMultiply,
372 CsdOperationType::VectorDotProduct,
373 CsdOperationType::Convolution,
374 CsdOperationType::Filter,
375 CsdOperationType::Aggregate,
376 ],
377 memory_size: 8 * 1024 * 1024 * 1024, compute_units: 64,
379 clock_speed: 1.5, };
381
382 let device = CsdDevice {
383 device_id: device_id.clone(),
384 device_path: device_path.to_string(),
385 capabilities,
386 supported_functions: vec![], device_stats: CsdDeviceStats {
388 operations_completed: 0,
389 total_execution_time: 0,
390 average_execution_time: 0.0,
391 data_processed: 0,
392 error_count: 0,
393 utilization: 0.0,
394 },
395 };
396
397 Ok(device)
398 }
399
400 pub fn register_function(&mut self, function: CsdFunction) -> Result<(), CsdError> {
402 self.validate_function(&function)?;
404
405 self.functions
407 .insert(function.function_id.clone(), function);
408
409 Ok(())
410 }
411
412 pub fn execute_operation(&mut self, operation: CsdOperationRequest) -> Result<u64, CsdError> {
414 self.validate_operation(&operation)?;
416
417 self.scheduler.schedule_operation(operation.clone())?;
419
420 Ok(operation.operation_id)
421 }
422
423 pub fn matrix_multiply(
425 &mut self,
426 device_id: &str,
427 a: &[f32],
428 b: &[f32],
429 dimensions: (usize, usize, usize),
430 ) -> Result<Vec<f32>, CsdError> {
431 let mut result = vec![0.0f32; dimensions.0 * dimensions.2];
432 let written = self.matrix_multiply_into(device_id, a, b, dimensions, &mut result)?;
433 result.truncate(written);
434 Ok(result)
435 }
436
437 pub fn matrix_multiply_into(
439 &mut self,
440 device_id: &str,
441 a: &[f32],
442 b: &[f32],
443 dimensions: (usize, usize, usize),
444 out: &mut [f32],
445 ) -> Result<usize, CsdError> {
446 self.ensure_device_exists(device_id)?;
447 let (rows_a, shared, cols_b) = dimensions;
448 if a.len() != rows_a * shared {
449 return Err(CsdError::InvalidOperation(
450 "matrix A dimensions do not match input length".to_string(),
451 ));
452 }
453 if b.len() != shared * cols_b {
454 return Err(CsdError::InvalidOperation(
455 "matrix B dimensions do not match input length".to_string(),
456 ));
457 }
458 let required = rows_a * cols_b;
459 if out.len() < required {
460 return Err(CsdError::BufferTooSmall(
461 "matrix multiply output buffer too small".to_string(),
462 ));
463 }
464
465 let operation_id = self.generate_operation_id();
466 let operation = CsdOperationRequest {
467 operation_id,
468 function_id: "matrix_multiply".to_string(),
469 device_id: device_id.to_string(),
470 inputs: vec![
471 OperationInput {
472 name: "matrix_a".to_string(),
473 data: self.f32_slice_to_bytes(a),
474 location: DataLocation::HostMemory,
475 },
476 OperationInput {
477 name: "matrix_b".to_string(),
478 data: self.f32_slice_to_bytes(b),
479 location: DataLocation::HostMemory,
480 },
481 OperationInput {
482 name: "dimensions".to_string(),
483 data: self.serialize_dimensions(dimensions),
484 location: DataLocation::HostMemory,
485 },
486 ],
487 outputs: vec![OperationOutput {
488 name: "result".to_string(),
489 size: (required * 4) as u64,
490 location: DataLocation::HostMemory,
491 }],
492 priority: OperationPriority::Normal,
493 deadline: None,
494 };
495 if self.execute_operation(operation).is_ok() {
496 if let Ok(completion) = self.wait_for_completion(operation_id) {
497 if let Some(output) = completion.outputs.first() {
498 let floats = self.bytes_to_f32_slice(output);
499 let n = floats.len().min(required);
500 out[..n].copy_from_slice(&floats[..n]);
501 return Ok(n);
502 }
503 }
504 }
505
506 for row in 0..rows_a {
507 for col in 0..cols_b {
508 let mut sum = 0.0f32;
509 for inner in 0..shared {
510 sum += a[row * shared + inner] * b[inner * cols_b + col];
511 }
512 out[row * cols_b + col] = sum;
513 }
514 }
515
516 Ok(required)
517 }
518
519 pub fn vector_dot_product(
521 &mut self,
522 device_id: &str,
523 a: &[f32],
524 b: &[f32],
525 ) -> Result<f32, CsdError> {
526 let operation_id = self.generate_operation_id();
527
528 let operation = CsdOperationRequest {
529 operation_id,
530 function_id: "vector_dot_product".to_string(),
531 device_id: device_id.to_string(),
532 inputs: vec![
533 OperationInput {
534 name: "vector_a".to_string(),
535 data: self.f32_slice_to_bytes(a),
536 location: DataLocation::HostMemory,
537 },
538 OperationInput {
539 name: "vector_b".to_string(),
540 data: self.f32_slice_to_bytes(b),
541 location: DataLocation::HostMemory,
542 },
543 ],
544 outputs: vec![OperationOutput {
545 name: "result".to_string(),
546 size: 4, location: DataLocation::HostMemory,
548 }],
549 priority: OperationPriority::Normal,
550 deadline: None,
551 };
552
553 self.execute_operation(operation)?;
554 let completion = self.wait_for_completion(operation_id)?;
555
556 if let Some(output) = completion.outputs.first() {
557 let result = self.bytes_to_f32_value(&output);
558 Ok(result)
559 } else {
560 Err(CsdError::NoOutput("No output generated".to_string()))
561 }
562 }
563
564 pub fn convolution(
566 &mut self,
567 device_id: &str,
568 input: &[f32],
569 kernel: &[f32],
570 dimensions: (usize, usize, usize, usize),
571 ) -> Result<Vec<f32>, CsdError> {
572 let mut result = vec![0.0f32; dimensions.0 * dimensions.1];
573 let written = self.convolution_into(device_id, input, kernel, dimensions, &mut result)?;
574 result.truncate(written);
575 Ok(result)
576 }
577
578 pub fn convolution_into(
580 &mut self,
581 device_id: &str,
582 input: &[f32],
583 kernel: &[f32],
584 dimensions: (usize, usize, usize, usize),
585 out: &mut [f32],
586 ) -> Result<usize, CsdError> {
587 self.ensure_device_exists(device_id)?;
588 let _dim_wire = self.serialize_convolution_dimensions(dimensions);
589 let (width, height, kernel_width, kernel_height) = dimensions;
590 if input.len() != width * height {
591 return Err(CsdError::InvalidOperation(
592 "convolution input dimensions do not match input length".to_string(),
593 ));
594 }
595 if kernel.len() != kernel_width * kernel_height {
596 return Err(CsdError::InvalidOperation(
597 "convolution kernel dimensions do not match kernel length".to_string(),
598 ));
599 }
600 let required = width * height;
601 if out.len() < required {
602 return Err(CsdError::BufferTooSmall(
603 "convolution output buffer too small".to_string(),
604 ));
605 }
606
607 let kernel_x_radius = kernel_width / 2;
608 let kernel_y_radius = kernel_height / 2;
609
610 for y in 0..height {
611 for x in 0..width {
612 let mut acc = 0.0f32;
613 for ky in 0..kernel_height {
614 let Some(input_y) = y
615 .checked_add(ky)
616 .and_then(|value| value.checked_sub(kernel_y_radius))
617 else {
618 continue;
619 };
620 if input_y >= height {
621 continue;
622 }
623 for kx in 0..kernel_width {
624 let Some(input_x) = x
625 .checked_add(kx)
626 .and_then(|value| value.checked_sub(kernel_x_radius))
627 else {
628 continue;
629 };
630 if input_x >= width {
631 continue;
632 }
633 let input_index = input_y * width + input_x;
634 let kernel_index = ky * kernel_width + kx;
635 acc += input[input_index] * kernel[kernel_index];
636 }
637 }
638 out[y * width + x] = acc;
639 }
640 }
641
642 Ok(required)
643 }
644
645 pub fn get_device_stats(&self, device_id: &str) -> Option<CsdDeviceStats> {
647 self.devices
648 .get(device_id)
649 .map(|device| device.device_stats.clone())
650 }
651
652 pub fn get_performance_stats(&self) -> CsdGlobalMetrics {
654 self.performance_monitor.get_global_stats()
655 }
656
657 pub fn list_devices(&self) -> Vec<String> {
659 self.devices.keys().cloned().collect()
660 }
661
662 pub fn list_devices_into(&self, out: &mut [CsdDeviceHandle]) -> Result<usize, CsdError> {
664 if out.len() < self.devices.len() {
665 return Err(CsdError::BufferTooSmall(
666 "device listing output buffer too small".to_string(),
667 ));
668 }
669
670 let mut written = 0;
671 for device in self.devices.values() {
672 out[written] = Self::device_handle(device);
673 written += 1;
674 }
675 Ok(written)
676 }
677
678 pub fn list_functions(&self) -> Vec<String> {
680 self.functions.keys().cloned().collect()
681 }
682
683 pub fn list_functions_into(&self, out: &mut [CsdFunctionHandle]) -> Result<usize, CsdError> {
685 if out.len() < self.functions.len() {
686 return Err(CsdError::BufferTooSmall(
687 "function listing output buffer too small".to_string(),
688 ));
689 }
690
691 let mut written = 0;
692 for function in self.functions.values() {
693 out[written] = Self::function_handle(function);
694 written += 1;
695 }
696 Ok(written)
697 }
698
699 fn validate_function(&self, function: &CsdFunction) -> Result<(), CsdError> {
703 if function.function_id.is_empty() {
704 return Err(CsdError::InvalidFunction(
705 "Function ID cannot be empty".to_string(),
706 ));
707 }
708
709 if function.bytecode.is_empty() {
710 return Err(CsdError::InvalidFunction(
711 "Function bytecode cannot be empty".to_string(),
712 ));
713 }
714
715 Ok(())
716 }
717
718 fn validate_operation(&self, operation: &CsdOperationRequest) -> Result<(), CsdError> {
720 if !self.devices.contains_key(&operation.device_id) {
722 return Err(CsdError::DeviceNotFound(operation.device_id.clone()));
723 }
724
725 if !self.functions.contains_key(&operation.function_id) {
727 return Err(CsdError::FunctionNotFound(operation.function_id.clone()));
728 }
729
730 if operation.inputs.is_empty() {
732 return Err(CsdError::InvalidOperation(
733 "Operation must have inputs".to_string(),
734 ));
735 }
736
737 Ok(())
738 }
739
740 fn ensure_device_exists(&self, device_id: &str) -> Result<(), CsdError> {
741 if self.devices.contains_key(device_id) {
742 Ok(())
743 } else {
744 Err(CsdError::DeviceNotFound(device_id.to_string()))
745 }
746 }
747
748 fn wait_for_completion(&self, operation_id: u64) -> Result<CsdCompletion, CsdError> {
750 Ok(CsdCompletion {
753 operation_id,
754 status: CompletionStatus::Success,
755 execution_time: 1000, outputs: vec![],
757 error_message: None,
758 })
759 }
760
761 fn generate_operation_id(&self) -> u64 {
763 use std::sync::atomic::{AtomicU64, Ordering};
764 static COUNTER: AtomicU64 = AtomicU64::new(1);
765 COUNTER.fetch_add(1, Ordering::SeqCst)
766 }
767
768 fn f32_slice_to_bytes(&self, slice: &[f32]) -> Vec<u8> {
770 let mut bytes = Vec::with_capacity(slice.len() * 4);
771 for &value in slice {
772 bytes.extend_from_slice(&value.to_le_bytes());
773 }
774 bytes
775 }
776
777 fn bytes_to_f32_slice(&self, output: &OperationOutput) -> Vec<f32> {
784 vec![0.0f32; (output.size / 4) as usize]
785 }
786
787 fn bytes_to_f32_value(&self, output: &OperationOutput) -> f32 {
789 let _ = output;
791 0.0f32
792 }
793
794 fn serialize_dimensions(&self, dimensions: (usize, usize, usize)) -> Vec<u8> {
796 let mut bytes = Vec::with_capacity(12);
797 bytes.extend_from_slice(&(dimensions.0 as u32).to_le_bytes());
798 bytes.extend_from_slice(&(dimensions.1 as u32).to_le_bytes());
799 bytes.extend_from_slice(&(dimensions.2 as u32).to_le_bytes());
800 bytes
801 }
802
803 fn serialize_convolution_dimensions(
805 &self,
806 dimensions: (usize, usize, usize, usize),
807 ) -> Vec<u8> {
808 let mut bytes = Vec::with_capacity(16);
809 bytes.extend_from_slice(&(dimensions.0 as u32).to_le_bytes());
810 bytes.extend_from_slice(&(dimensions.1 as u32).to_le_bytes());
811 bytes.extend_from_slice(&(dimensions.2 as u32).to_le_bytes());
812 bytes.extend_from_slice(&(dimensions.3 as u32).to_le_bytes());
813 bytes
814 }
815
816 fn device_handle(device: &CsdDevice) -> CsdDeviceHandle {
817 CsdDeviceHandle {
818 device_id_hash: q_hash(&device.device_id),
819 max_concurrent_operations: device.capabilities.max_concurrent_operations,
820 max_data_size: device.capabilities.max_data_size,
821 memory_size: device.capabilities.memory_size,
822 compute_units: device.capabilities.compute_units,
823 }
824 }
825
826 fn function_handle(function: &CsdFunction) -> CsdFunctionHandle {
827 CsdFunctionHandle {
828 function_id_hash: q_hash(&function.function_id),
829 operation_tag: Self::operation_tag(&function.operation),
830 parameter_count: function.parameters.len() as u16,
831 bytecode_len: function.bytecode.len() as u32,
832 }
833 }
834
835 fn operation_tag(operation: &CsdOperationType) -> u8 {
836 match operation {
837 CsdOperationType::MatrixMultiply => 0x01,
838 CsdOperationType::VectorDotProduct => 0x02,
839 CsdOperationType::Convolution => 0x03,
840 CsdOperationType::Filter => 0x04,
841 CsdOperationType::Aggregate => 0x05,
842 CsdOperationType::Sort => 0x06,
843 CsdOperationType::Search => 0x07,
844 CsdOperationType::Custom(_) => 0xFF,
845 }
846 }
847}
848
849impl CsdScheduler {
850 pub fn new() -> Self {
852 Self {
853 pending_operations: Vec::new(),
854 running_operations: HashMap::new(),
855 completion_queue: Vec::new(),
856 scheduling_policy: SchedulingPolicy::Priority,
857 }
858 }
859
860 pub fn schedule_operation(&mut self, operation: CsdOperationRequest) -> Result<(), CsdError> {
862 self.pending_operations.push(operation);
863 Ok(())
864 }
865
866 pub fn process_operations(&mut self) -> Vec<CsdCompletion> {
868 match self.scheduling_policy {
869 SchedulingPolicy::Priority => self.pending_operations.sort_by_key(|op| {
870 std::cmp::Reverse(match op.priority {
871 OperationPriority::Critical => 3u8,
872 OperationPriority::High => 2,
873 OperationPriority::Normal => 1,
874 OperationPriority::Low => 0,
875 })
876 }),
877 SchedulingPolicy::ShortestJobFirst => self
878 .pending_operations
879 .sort_by_key(|op| op.outputs.iter().map(|o| o.size).sum::<u64>()),
880 _ => {}
881 }
882
883 let mut completions = Vec::new();
884
885 while let Some(operation) = self.pending_operations.pop() {
886 self.running_operations.insert(
887 operation.operation_id,
888 CsdRunningOperation {
889 operation_id: operation.operation_id,
890 device_id: operation.device_id.clone(),
891 start_time: 0,
892 progress: 0.0,
893 },
894 );
895 let completion = self.execute_operation(&operation);
896 self.running_operations.remove(&operation.operation_id);
897 self.completion_queue.push(completion.clone());
898 completions.push(completion);
899 }
900
901 completions
902 }
903
904 pub fn drain_completions(&mut self) -> Vec<CsdCompletion> {
906 std::mem::take(&mut self.completion_queue)
907 }
908
909 fn execute_operation(&self, operation: &CsdOperationRequest) -> CsdCompletion {
911 CsdCompletion {
912 operation_id: operation.operation_id,
913 status: CompletionStatus::Success,
914 execution_time: 1000, outputs: operation.outputs.clone(),
916 error_message: None,
917 }
918 }
919}
920
921impl CsdScheduler {
922 pub fn record_completion_metrics(
924 &self,
925 monitor: &mut CsdPerformanceMonitor,
926 operation: &CsdOperationRequest,
927 completion: &CsdCompletion,
928 ) {
929 let data_size = operation.outputs.iter().map(|o| o.size).sum::<u64>();
930 monitor.update_metrics(
931 &operation.device_id,
932 &operation.function_id,
933 completion.execution_time,
934 data_size,
935 );
936 }
937}
938
939impl CsdPerformanceMonitor {
940 pub fn new() -> Self {
942 Self {
943 device_metrics: HashMap::new(),
944 function_metrics: HashMap::new(),
945 global_metrics: CsdGlobalMetrics {
946 total_operations: 0,
947 total_execution_time: 0,
948 average_execution_time: 0.0,
949 total_data_processed: 0,
950 overall_throughput: 0.0,
951 system_utilization: 0.0,
952 },
953 }
954 }
955
956 pub fn update_metrics(
958 &mut self,
959 device_id: &str,
960 function_id: &str,
961 execution_time: u64,
962 data_size: u64,
963 ) {
964 self.device_metrics
965 .entry(device_id.to_string())
966 .or_insert(CsdDeviceMetrics {
967 device_id: device_id.to_string(),
968 utilization: 0.0,
969 throughput: 0.0,
970 latency: 0.0,
971 error_rate: 0.0,
972 power_consumption: 0.0,
973 })
974 .throughput += data_size as f64;
975 let func = self
976 .function_metrics
977 .entry(function_id.to_string())
978 .or_insert(CsdFunctionMetrics {
979 function_id: function_id.to_string(),
980 execution_count: 0,
981 total_execution_time: 0,
982 average_execution_time: 0.0,
983 success_rate: 1.0,
984 data_throughput: 0.0,
985 });
986 func.execution_count += 1;
987 func.total_execution_time += execution_time;
988 func.data_throughput += data_size as f64;
989
990 self.global_metrics.total_operations += 1;
991 self.global_metrics.total_execution_time += execution_time;
992 self.global_metrics.average_execution_time = self.global_metrics.total_execution_time
993 as f64
994 / self.global_metrics.total_operations as f64;
995 self.global_metrics.total_data_processed += data_size;
996 self.global_metrics.overall_throughput = self.global_metrics.total_data_processed as f64
997 / self.global_metrics.total_execution_time as f64;
998 }
999
1000 pub fn get_global_stats(&self) -> CsdGlobalMetrics {
1002 self.global_metrics.clone()
1003 }
1004}
1005
1006impl MathComputationBuilder {
1007 pub fn new() -> Self {
1009 Self {
1010 operations: Vec::new(),
1011 data_dependencies: HashMap::new(),
1012 execution_plan: ExecutionPlan {
1013 stages: Vec::new(),
1014 parallel_groups: Vec::new(),
1015 estimated_time: 0.0,
1016 resource_requirements: ResourceRequirements {
1017 memory_usage: 0,
1018 compute_units: 0,
1019 bandwidth: 0.0,
1020 },
1021 },
1022 }
1023 }
1024
1025 pub fn add_matrix_multiply(
1027 &mut self,
1028 device_id: String,
1029 a: Vec<f32>,
1030 b: Vec<f32>,
1031 dimensions: (usize, usize, usize),
1032 ) -> &mut Self {
1033 let operation_id = self.generate_operation_id();
1034
1035 let operation = CsdOperationRequest {
1036 operation_id,
1037 function_id: "matrix_multiply".to_string(),
1038 device_id,
1039 inputs: vec![
1040 OperationInput {
1041 name: "matrix_a".to_string(),
1042 data: self.f32_slice_to_bytes(&a),
1043 location: DataLocation::HostMemory,
1044 },
1045 OperationInput {
1046 name: "matrix_b".to_string(),
1047 data: self.f32_slice_to_bytes(&b),
1048 location: DataLocation::HostMemory,
1049 },
1050 ],
1051 outputs: vec![OperationOutput {
1052 name: format!("result_{}", operation_id),
1053 size: ((dimensions.0 * dimensions.2) * 4) as u64,
1054 location: DataLocation::HostMemory,
1055 }],
1056 priority: OperationPriority::Normal,
1057 deadline: None,
1058 };
1059
1060 self.operations.push(operation);
1061 self
1062 }
1063
1064 pub fn build(&mut self) -> Result<ExecutionPlan, CsdError> {
1066 self.analyze_dependencies();
1068
1069 self.create_execution_stages();
1071
1072 self.estimate_execution_time();
1074
1075 Ok(self.execution_plan.clone())
1076 }
1077
1078 fn analyze_dependencies(&mut self) {
1080 for (i, operation) in self.operations.iter().enumerate() {
1082 let mut dependencies = Vec::new();
1083
1084 for j in 0..i {
1086 let prev_operation = &self.operations[j];
1087
1088 for output in &prev_operation.outputs {
1090 for input in &operation.inputs {
1091 if input.name.contains(&output.name) {
1092 dependencies.push(prev_operation.function_id.clone());
1093 }
1094 }
1095 }
1096 }
1097
1098 self.data_dependencies
1099 .insert(operation.function_id.clone(), dependencies);
1100 }
1101 }
1102
1103 fn create_execution_stages(&mut self) {
1105 let mut stage_id = 0;
1107 let mut processed_operations = std::collections::HashSet::new();
1108
1109 while processed_operations.len() < self.operations.len() {
1110 let mut current_stage = Vec::new();
1111 let mut stage_dependencies = Vec::new();
1112
1113 for operation in &self.operations {
1114 if !processed_operations.contains(&operation.function_id) {
1115 let dependencies = self
1116 .data_dependencies
1117 .get(&operation.function_id)
1118 .cloned()
1119 .unwrap_or_default();
1120
1121 let can_execute = dependencies
1123 .iter()
1124 .all(|dep| processed_operations.contains(dep));
1125
1126 if can_execute {
1127 current_stage.push(operation.function_id.clone());
1128 stage_dependencies.extend(dependencies.clone());
1129 }
1130 }
1131 }
1132
1133 if current_stage.is_empty() {
1134 break; }
1136
1137 let stage = ExecutionStage {
1138 stage_id,
1139 operations: current_stage.clone(),
1140 dependencies: stage_dependencies,
1141 estimated_time: 1.0, };
1143
1144 self.execution_plan.stages.push(stage);
1145
1146 for operation in ¤t_stage {
1147 processed_operations.insert(operation.clone());
1148 }
1149
1150 stage_id += 1;
1151 }
1152 }
1153
1154 fn estimate_execution_time(&mut self) {
1156 let mut total_time = 0.0;
1157
1158 for stage in &self.execution_plan.stages {
1159 total_time += stage.estimated_time;
1160 }
1161
1162 self.execution_plan.estimated_time = total_time;
1163 }
1164
1165 fn generate_operation_id(&self) -> u64 {
1167 use std::sync::atomic::{AtomicU64, Ordering};
1168 static COUNTER: AtomicU64 = AtomicU64::new(1);
1169 COUNTER.fetch_add(1, Ordering::SeqCst)
1170 }
1171
1172 fn f32_slice_to_bytes(&self, slice: &[f32]) -> Vec<u8> {
1174 let mut bytes = Vec::with_capacity(slice.len() * 4);
1175 for &value in slice {
1176 bytes.extend_from_slice(&value.to_le_bytes());
1177 }
1178 bytes
1179 }
1180}
1181
1182#[derive(Debug, Clone)]
1184pub enum CsdError {
1185 DeviceOpen(String),
1186 DeviceNotFound(String),
1187 FunctionNotFound(String),
1188 InvalidFunction(String),
1189 InvalidOperation(String),
1190 NoOutput(String),
1191 ExecutionError(String),
1192 ConfigurationError(String),
1193 BufferTooSmall(String),
1194}
1195
1196impl std::fmt::Display for CsdError {
1197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1198 match self {
1199 CsdError::DeviceOpen(msg) => write!(f, "Device open error: {}", msg),
1200 CsdError::DeviceNotFound(msg) => write!(f, "Device not found: {}", msg),
1201 CsdError::FunctionNotFound(msg) => write!(f, "Function not found: {}", msg),
1202 CsdError::InvalidFunction(msg) => write!(f, "Invalid function: {}", msg),
1203 CsdError::InvalidOperation(msg) => write!(f, "Invalid operation: {}", msg),
1204 CsdError::NoOutput(msg) => write!(f, "No output: {}", msg),
1205 CsdError::ExecutionError(msg) => write!(f, "Execution error: {}", msg),
1206 CsdError::ConfigurationError(msg) => write!(f, "Configuration error: {}", msg),
1207 CsdError::BufferTooSmall(msg) => write!(f, "Buffer too small: {}", msg),
1208 }
1209 }
1210}
1211
1212impl std::error::Error for CsdError {}
1213
1214#[cfg(test)]
1215mod tests {
1216 use super::*;
1217
1218 #[test]
1219 fn test_csd_manager_creation() {
1220 let manager = CsdManager::new();
1221 assert_eq!(manager.list_devices().len(), 0);
1222 assert_eq!(manager.list_functions().len(), 0);
1223 }
1224
1225 #[test]
1226 fn test_matrix_multiply() {
1227 let mut manager = CsdManager::new();
1228
1229 let device = CsdDevice {
1231 device_id: "test_device".to_string(),
1232 device_path: "/dev/nvme0".to_string(),
1233 capabilities: CsdCapabilities {
1234 max_concurrent_operations: 16,
1235 max_data_size: 1024 * 1024 * 1024,
1236 supported_operations: vec![CsdOperationType::MatrixMultiply],
1237 memory_size: 8 * 1024 * 1024 * 1024,
1238 compute_units: 64,
1239 clock_speed: 1.5,
1240 },
1241 supported_functions: vec![],
1242 device_stats: CsdDeviceStats {
1243 operations_completed: 0,
1244 total_execution_time: 0,
1245 average_execution_time: 0.0,
1246 data_processed: 0,
1247 error_count: 0,
1248 utilization: 0.0,
1249 },
1250 };
1251
1252 manager.register_device(device).unwrap();
1253
1254 let a = vec![1.0_f32, 2.0_f32, 3.0_f32, 4.0_f32];
1257 let b = vec![5.0_f32, 6.0_f32, 7.0_f32, 8.0_f32];
1258
1259 let result = manager
1261 .matrix_multiply("test_device", &a, &b, (2, 2, 2))
1262 .unwrap();
1263 assert_eq!(result.len(), 4);
1264 }
1265
1266 #[test]
1267 fn test_math_computation_builder() {
1268 let mut builder = MathComputationBuilder::new();
1269
1270 let a = vec![1.0, 2.0, 3.0, 4.0];
1271 let b = vec![5.0, 6.0, 7.0, 8.0];
1272
1273 builder.add_matrix_multiply("device1".to_string(), a, b, (2, 2, 2));
1274
1275 let plan = builder.build();
1276 assert!(plan.is_ok());
1277
1278 if let Ok(plan) = plan {
1279 assert_eq!(plan.stages.len(), 1);
1280 assert!(plan.estimated_time > 0.0);
1281 }
1282 }
1283}