tenflowers_core/
dispatch_init.rs1use crate::dispatch_registry_examples::initialize_dispatch_registrations;
9use crate::dispatch_registry_extended::initialize_extended_registrations;
10
11use lazy_static::lazy_static;
12
13lazy_static! {
14 pub static ref DISPATCH_INIT: () = {
16 initialize_dispatch_registrations();
17 initialize_extended_registrations();
18 #[cfg(feature = "gpu")]
19 initialize_gpu_operations();
20 };
21}
22
23#[cfg(feature = "gpu")]
25fn initialize_gpu_operations() {
26 register_gpu_reductions();
30}
31
32#[cfg(feature = "gpu")]
34fn register_gpu_reductions() {
35 use crate::dispatch_registry::{
36 BackendType, KernelImplementation, OperationDescriptor, F32_REGISTRY,
37 };
38 use crate::DType;
39
40 {
42 let desc = OperationDescriptor::new("sum", "reduction").with_dtypes(vec![DType::Float32]);
43
44 if F32_REGISTRY.get_operation("sum").is_none() {
46 F32_REGISTRY.register_operation(desc).ok();
47 }
48
49 F32_REGISTRY
54 .register_kernel(
55 "sum",
56 KernelImplementation::unary(BackendType::Cpu, sum_f32_cpu),
57 )
58 .ok();
59
60 F32_REGISTRY
62 .register_kernel(
63 "sum",
64 KernelImplementation::unary(BackendType::Gpu, sum_f32_gpu),
65 )
66 .ok();
67 }
68
69 {
71 let desc = OperationDescriptor::new("mean", "reduction").with_dtypes(vec![DType::Float32]);
72
73 if F32_REGISTRY.get_operation("mean").is_none() {
74 F32_REGISTRY.register_operation(desc).ok();
75 }
76
77 F32_REGISTRY
79 .register_kernel(
80 "mean",
81 KernelImplementation::unary(BackendType::Cpu, mean_f32_cpu),
82 )
83 .ok();
84
85 F32_REGISTRY
87 .register_kernel(
88 "mean",
89 KernelImplementation::unary(BackendType::Gpu, mean_f32_gpu),
90 )
91 .ok();
92 }
93}
94
95#[cfg(feature = "gpu")]
97fn sum_f32_gpu(x: &crate::Tensor<f32>) -> crate::Result<crate::Tensor<f32>> {
98 use crate::gpu::buffer::GpuBuffer;
99 use crate::gpu::ops::operation_types::ReductionOp;
100 use crate::gpu::ops::reduction_ops::execute_reduction_op;
101 use crate::Device;
102 use scirs2_core::ndarray::Array;
103
104 let slice = x.data();
106
107 let gpu_buffer = GpuBuffer::from_slice(slice, &Device::Gpu(0))?;
109
110 let result_buffer = execute_reduction_op(&gpu_buffer, ReductionOp::Sum, None)?;
112
113 let result_data = result_buffer.to_cpu()?;
115
116 let result = Array::from_elem(vec![], result_data[0]).into_dyn();
118 Ok(crate::Tensor::from_array(result))
119}
120
121#[cfg(feature = "gpu")]
123fn mean_f32_gpu(x: &crate::Tensor<f32>) -> crate::Result<crate::Tensor<f32>> {
124 use crate::gpu::buffer::GpuBuffer;
125 use crate::gpu::ops::operation_types::ReductionOp;
126 use crate::gpu::ops::reduction_ops::execute_reduction_op;
127 use crate::Device;
128 use scirs2_core::ndarray::Array;
129
130 let slice = x.data();
132
133 let gpu_buffer = GpuBuffer::from_slice(slice, &Device::Gpu(0))?;
135
136 let result_buffer = execute_reduction_op(&gpu_buffer, ReductionOp::Mean, None)?;
138
139 let result_data = result_buffer.to_cpu()?;
141
142 let result = Array::from_elem(vec![], result_data[0]).into_dyn();
144 Ok(crate::Tensor::from_array(result))
145}
146
147fn sum_f32_cpu(x: &crate::Tensor<f32>) -> crate::Result<crate::Tensor<f32>> {
149 use scirs2_core::ndarray::Array;
150
151 let data = x.data();
152 let sum: f32 = data.iter().sum();
153 let result = Array::from_elem(vec![], sum).into_dyn();
154 Ok(crate::Tensor::from_array(result))
155}
156
157fn mean_f32_cpu(x: &crate::Tensor<f32>) -> crate::Result<crate::Tensor<f32>> {
159 use scirs2_core::ndarray::Array;
160
161 let data = x.data();
162 let sum: f32 = data.iter().sum();
163 let mean = sum / data.len() as f32;
164 let result = Array::from_elem(vec![], mean).into_dyn();
165 Ok(crate::Tensor::from_array(result))
166}
167
168pub fn ensure_initialized() {
174 *DISPATCH_INIT;
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180 use crate::Tensor;
181 use scirs2_core::ndarray::array;
182
183 #[test]
184 fn test_initialization() {
185 ensure_initialized();
186
187 use crate::dispatch_registry::F32_REGISTRY;
188
189 assert!(F32_REGISTRY.get_operation("add").is_some());
191 assert!(F32_REGISTRY.get_operation("mul").is_some());
192 assert!(F32_REGISTRY.get_operation("div").is_some());
193 }
194
195 #[test]
196 fn test_sum_cpu_fallback() {
197 let input = Tensor::from_array(array![1.0f32, 2.0, 3.0, 4.0, 5.0].into_dyn());
198 let result = sum_f32_cpu(&input).expect("test: sum_f32_cpu should succeed");
199
200 assert_eq!(result.data()[0], 15.0);
202 }
203
204 #[test]
205 fn test_mean_cpu_fallback() {
206 let input = Tensor::from_array(array![1.0f32, 2.0, 3.0, 4.0, 5.0].into_dyn());
207 let result = mean_f32_cpu(&input).expect("test: mean_f32_cpu should succeed");
208
209 assert_eq!(result.data()[0], 3.0);
211 }
212}