1use std::collections::HashMap;
7use std::fmt;
8
9pub mod blas;
10pub mod complex;
11pub mod elementwise;
12pub mod ml;
13pub mod reduction;
14pub mod transform;
15
16use crate::gpu::{GpuBackend, GpuError};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub enum DataType {
21 Float32,
23 Float64,
25 Int32,
27 UInt32,
29 Float16,
31 BFloat16,
33}
34
35impl fmt::Display for DataType {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 DataType::Float32 => write!(f, "f32"),
39 DataType::Float64 => write!(f, "f64"),
40 DataType::Int32 => write!(f, "i32"),
41 DataType::UInt32 => write!(f, "u32"),
42 DataType::Float16 => write!(f, "f16"),
43 DataType::BFloat16 => write!(f, "bf16"),
44 }
45 }
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum OperationType {
51 ComputeIntensive,
53 MemoryIntensive,
55 Balanced,
57}
58
59#[derive(Debug, Clone)]
61pub struct KernelMetadata {
62 pub workgroup_size: [u32; 3],
64 pub local_memory_usage: usize,
66 pub supports_tensor_cores: bool,
68 pub operationtype: OperationType,
70 pub backend_metadata: HashMap<String, String>,
72}
73
74impl Default for KernelMetadata {
75 fn default() -> Self {
76 Self {
77 workgroup_size: [16, 16, 1],
78 local_memory_usage: 0,
79 supports_tensor_cores: false,
80 operationtype: OperationType::Balanced,
81 backend_metadata: HashMap::new(),
82 }
83 }
84}
85
86#[derive(Debug, Clone)]
88pub struct KernelParams {
89 pub datatype: DataType,
91 pub input_dims: Vec<usize>,
93 pub output_dims: Vec<usize>,
95 pub numeric_params: HashMap<String, f64>,
97 pub string_params: HashMap<String, String>,
99}
100
101impl KernelParams {
102 pub fn new(datatype: DataType) -> Self {
104 Self {
105 datatype,
106 input_dims: Vec::new(),
107 output_dims: Vec::new(),
108 numeric_params: HashMap::new(),
109 string_params: HashMap::new(),
110 }
111 }
112
113 pub fn with_input_dims(mut self, dims: Vec<usize>) -> Self {
115 self.input_dims = dims;
116 self
117 }
118
119 pub fn with_output_dims(mut self, dims: Vec<usize>) -> Self {
121 self.output_dims = dims;
122 self
123 }
124
125 pub fn with_numeric_param(mut self, name: &str, value: f64) -> Self {
127 self.numeric_params.insert(name.to_string(), value);
128 self
129 }
130
131 pub fn with_string_param(mut self, name: &str, value: &str) -> Self {
133 self.string_params
134 .insert(name.to_string(), value.to_string());
135 self
136 }
137}
138
139pub trait GpuKernel: Send + Sync {
141 fn name(&self) -> &str;
143
144 fn source_for_backend(&self, backend: GpuBackend) -> Result<String, GpuError>;
146
147 fn metadata(&self) -> KernelMetadata;
149
150 fn can_specialize(&self, params: &KernelParams) -> bool;
152
153 fn specialize(&self, params: &KernelParams) -> Result<Box<dyn GpuKernel>, GpuError>;
155}
156
157pub struct BaseKernel {
159 name: String,
160 cuda_source: String,
161 rocm_source: String,
162 wgpu_source: String,
163 metal_source: String,
164 opencl_source: String,
165 metadata: KernelMetadata,
166}
167
168impl BaseKernel {
169 pub fn new(
171 name: &str,
172 cuda_source: &str,
173 rocm_source: &str,
174 wgpu_source: &str,
175 metal_source: &str,
176 opencl_source: &str,
177 metadata: KernelMetadata,
178 ) -> Self {
179 Self {
180 name: name.to_string(),
181 cuda_source: cuda_source.to_string(),
182 rocm_source: rocm_source.to_string(),
183 wgpu_source: wgpu_source.to_string(),
184 metal_source: metal_source.to_string(),
185 opencl_source: opencl_source.to_string(),
186 metadata,
187 }
188 }
189}
190
191impl GpuKernel for BaseKernel {
192 fn name(&self) -> &str {
193 &self.name
194 }
195
196 fn source_for_backend(&self, backend: GpuBackend) -> Result<String, GpuError> {
197 match backend {
198 GpuBackend::Cuda => Ok(self.cuda_source.clone()),
199 GpuBackend::Rocm => Ok(self.rocm_source.clone()),
200 GpuBackend::Wgpu => Ok(self.wgpu_source.clone()),
201 GpuBackend::Metal => Ok(self.metal_source.clone()),
202 GpuBackend::OpenCL => Ok(self.opencl_source.clone()),
203 _ => Err(GpuError::UnsupportedBackend(backend)),
204 }
205 }
206
207 fn metadata(&self) -> KernelMetadata {
208 self.metadata.clone()
209 }
210
211 fn can_specialize(&self, params: &KernelParams) -> bool {
212 false }
214
215 fn specialize(&self, params: &KernelParams) -> Result<Box<dyn GpuKernel>, GpuError> {
216 Err(GpuError::SpecializationNotSupported)
217 }
218}
219
220pub struct KernelRegistry {
222 kernels: HashMap<String, Box<dyn GpuKernel>>,
223}
224
225impl KernelRegistry {
226 pub fn new() -> Self {
228 Self {
229 kernels: HashMap::new(),
230 }
231 }
232
233 pub fn with_default_kernels() -> Self {
235 let mut registry = Self::new();
236
237 registry.register(Box::new(blas::gemm::GemmKernel::new()));
239 registry.register(Box::new(blas::axpy::AxpyKernel::new()));
240 registry.register(Box::new(blas::gemv::GemvKernel::new()));
241
242 registry.register(Box::new(elementwise::ElementwiseAddKernel::new()));
244 registry.register(Box::new(elementwise::ElementwiseSubKernel::new()));
245 registry.register(Box::new(elementwise::ElementwiseMulKernel::new()));
246 registry.register(Box::new(elementwise::ElementwiseDivKernel::new()));
247 registry.register(Box::new(elementwise::ElementwisePowKernel::new()));
248 registry.register(Box::new(elementwise::ElementwiseSqrtKernel::new()));
249 registry.register(Box::new(elementwise::ElementwiseExpKernel::new()));
250 registry.register(Box::new(elementwise::ElementwiseLogKernel::new()));
251
252 registry.register(Box::new(create_adam_optimizer_kernel()));
254 registry.register(Box::new(create_sgd_optimizer_kernel()));
255 registry.register(Box::new(create_rmsprop_optimizer_kernel()));
256 registry.register(Box::new(create_adagrad_optimizer_kernel()));
257 registry.register(Box::new(create_lamb_optimizer_kernel()));
258
259 registry.register(Box::new(create_memcpy_kernel()));
261 registry.register(Box::new(create_fill_kernel()));
262 registry.register(Box::new(create_reduce_sum_kernel()));
263 registry.register(Box::new(create_reduce_max_kernel()));
264
265 registry.register(Box::new(transform::fft::FftKernel::new()));
267 registry.register(Box::new(transform::convolution::Conv1dKernel::new()));
268 registry.register(Box::new(transform::convolution::Conv2dKernel::new()));
269
270 registry.register(Box::new(reduction::sum::SumKernel::new()));
272 registry.register(Box::new(reduction::norm::NormKernel::new()));
273 registry.register(Box::new(reduction::min_max::MinKernel::new()));
274 registry.register(Box::new(reduction::min_max::MaxKernel::new()));
275 registry.register(Box::new(reduction::mean::MeanKernel::new()));
276 registry.register(Box::new(reduction::std_dev::StdDevKernel::new()));
277
278 registry.register(Box::new(ml::activation::ReluKernel::new()));
280 registry.register(Box::new(ml::activation::SigmoidKernel::new()));
281 registry.register(Box::new(ml::activation::TanhKernel::new()));
282 registry.register(Box::new(ml::softmax::SoftmaxKernel::new()));
283 registry.register(Box::new(ml::pooling::MaxPoolKernel::new()));
284 registry.register(Box::new(ml::pooling::AvgPoolKernel::new()));
285
286 registry.register(Box::new(complex::ComplexMultiplyKernel::new()));
288 registry.register(Box::new(complex::ComplexConjugateKernel::new()));
289 registry.register(Box::new(complex::ComplexMatMulKernel::new()));
290
291 registry.register(Box::new(create_rk4_stage1_kernel()));
293 registry.register(Box::new(create_rk4_stage2_kernel()));
294 registry.register(Box::new(create_rk4_stage3_kernel()));
295 registry.register(Box::new(create_rk4_stage4_kernel()));
296 registry.register(Box::new(create_rk4_combine_kernel()));
297 registry.register(Box::new(createerror_estimate_kernel()));
298
299 registry
300 }
301
302 pub fn register(&mut self, kernel: Box<dyn GpuKernel>) {
304 self.kernels.insert(kernel.name().to_string(), kernel);
305 }
306
307 pub fn get(&self, name: &str) -> Option<&dyn GpuKernel> {
309 self.kernels.get(name).map(|k| k.as_ref())
310 }
311
312 pub fn get_specialized(
314 &self,
315 name: &str,
316 params: &KernelParams,
317 ) -> Result<Box<dyn GpuKernel>, GpuError> {
318 let kernel = self
319 .get(name)
320 .ok_or_else(|| GpuError::KernelNotFound(name.to_string()))?;
321
322 if kernel.can_specialize(params) {
323 kernel.specialize(params)
324 } else {
325 Err(GpuError::SpecializationNotSupported)
326 }
327 }
328}
329
330impl Default for KernelRegistry {
331 fn default() -> Self {
332 Self::with_default_kernels()
333 }
334}
335
336const ADAM_WGSL: &str = r#"
344@group(0) @binding(0) var<storage, read_write> params: array<f32>;
345@group(0) @binding(1) var<storage, read> grads: array<f32>;
346@group(0) @binding(2) var<storage, read_write> m: array<f32>;
347@group(0) @binding(3) var<storage, read_write> v: array<f32>;
348
349struct AdamUniforms {
350 lr: f32,
351 beta1: f32,
352 beta2: f32,
353 eps: f32,
354 weight_decay: f32,
355 bias_correction1: f32,
356 bias_correction2: f32,
357 n: u32,
358};
359
360@group(0) @binding(4) var<uniform> uniforms: AdamUniforms;
361
362@compute @workgroup_size(256)
363fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
364 let idx = global_id.x;
365 if idx >= uniforms.n { return; }
366
367 var grad = grads[idx];
368 if uniforms.weight_decay > 0.0 {
369 grad += uniforms.weight_decay * params[idx];
370 }
371
372 // Update biased first moment estimate
373 m[idx] = uniforms.beta1 * m[idx] + (1.0 - uniforms.beta1) * grad;
374
375 // Update biased second raw moment estimate
376 v[idx] = uniforms.beta2 * v[idx] + (1.0 - uniforms.beta2) * grad * grad;
377
378 // Bias-corrected moment estimates
379 let m_hat = m[idx] / uniforms.bias_correction1;
380 let v_hat = v[idx] / uniforms.bias_correction2;
381
382 // Parameter update
383 params[idx] -= uniforms.lr * m_hat / (sqrt(v_hat) + uniforms.eps);
384}
385"#;
386
387const SGD_WGSL: &str = r#"
392@group(0) @binding(0) var<storage, read_write> params: array<f32>;
393@group(0) @binding(1) var<storage, read> grads: array<f32>;
394@group(0) @binding(2) var<storage, read_write> momentum_buf: array<f32>;
395
396struct SgdUniforms {
397 lr: f32,
398 momentum_factor: f32,
399 n: u32,
400};
401
402@group(0) @binding(3) var<uniform> uniforms: SgdUniforms;
403
404@compute @workgroup_size(256)
405fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
406 let idx = global_id.x;
407 if idx >= uniforms.n { return; }
408
409 let grad = grads[idx];
410 if uniforms.momentum_factor > 0.0 {
411 // SGD with momentum: buf = momentum * buf + grad; param -= lr * buf
412 let buf = uniforms.momentum_factor * momentum_buf[idx] + grad;
413 momentum_buf[idx] = buf;
414 params[idx] -= uniforms.lr * buf;
415 } else {
416 params[idx] -= uniforms.lr * grad;
417 }
418}
419"#;
420
421const RMSPROP_WGSL: &str = r#"
426@group(0) @binding(0) var<storage, read_write> params: array<f32>;
427@group(0) @binding(1) var<storage, read> grads: array<f32>;
428@group(0) @binding(2) var<storage, read_write> cache: array<f32>;
429
430struct RmspropUniforms {
431 lr: f32,
432 decay: f32,
433 epsilon: f32,
434 n: u32,
435};
436
437@group(0) @binding(3) var<uniform> uniforms: RmspropUniforms;
438
439@compute @workgroup_size(256)
440fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
441 let idx = global_id.x;
442 if idx >= uniforms.n { return; }
443
444 let grad = grads[idx];
445 // cache = decay * cache + (1 - decay) * grad^2
446 let new_cache = uniforms.decay * cache[idx] + (1.0 - uniforms.decay) * grad * grad;
447 cache[idx] = new_cache;
448 // params -= lr * grad / (sqrt(cache) + epsilon)
449 params[idx] -= uniforms.lr * grad / (sqrt(new_cache) + uniforms.epsilon);
450}
451"#;
452
453const ADAGRAD_WGSL: &str = r#"
458@group(0) @binding(0) var<storage, read_write> params: array<f32>;
459@group(0) @binding(1) var<storage, read> grads: array<f32>;
460@group(0) @binding(2) var<storage, read_write> cache: array<f32>;
461
462struct AdagradUniforms {
463 lr: f32,
464 epsilon: f32,
465 n: u32,
466};
467
468@group(0) @binding(3) var<uniform> uniforms: AdagradUniforms;
469
470@compute @workgroup_size(256)
471fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
472 let idx = global_id.x;
473 if idx >= uniforms.n { return; }
474
475 let grad = grads[idx];
476 // Accumulate squared gradient
477 let new_cache = cache[idx] + grad * grad;
478 cache[idx] = new_cache;
479 // Adaptive update
480 params[idx] -= uniforms.lr * grad / (sqrt(new_cache) + uniforms.epsilon);
481}
482"#;
483
484const LAMB_WGSL: &str = r#"
492@group(0) @binding(0) var<storage, read_write> params: array<f32>;
493@group(0) @binding(1) var<storage, read> grads: array<f32>;
494
495struct LambUniforms {
496 lr: f32,
497 weight_decay: f32,
498 param_norm: f32,
499 grad_norm: f32,
500 n: u32,
501};
502
503@group(0) @binding(2) var<uniform> uniforms: LambUniforms;
504
505@compute @workgroup_size(256)
506fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
507 let idx = global_id.x;
508 if idx >= uniforms.n { return; }
509
510 // update = grad + weight_decay * param
511 let update = grads[idx] + uniforms.weight_decay * params[idx];
512
513 // Layer-wise adaptive ratio: trust_ratio = param_norm / (grad_norm + eps)
514 // Guard against zero norms (use 1.0 as neutral ratio)
515 let eps = 1e-6;
516 let denom = uniforms.grad_norm + eps;
517 let trust_ratio = select(1.0, uniforms.param_norm / denom, uniforms.param_norm > 0.0 && uniforms.grad_norm > 0.0);
518
519 params[idx] -= uniforms.lr * trust_ratio * update;
520}
521"#;
522
523const MEMCPY_WGSL: &str = r#"
528@group(0) @binding(0) var<storage, read> src: array<f32>;
529@group(0) @binding(1) var<storage, read_write> dst: array<f32>;
530
531struct MemcpyUniforms {
532 n: u32,
533};
534
535@group(0) @binding(2) var<uniform> uniforms: MemcpyUniforms;
536
537@compute @workgroup_size(256)
538fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
539 let idx = global_id.x;
540 if idx >= uniforms.n { return; }
541 dst[idx] = src[idx];
542}
543"#;
544
545const FILL_WGSL: &str = r#"
550@group(0) @binding(0) var<storage, read_write> dst: array<f32>;
551
552struct FillUniforms {
553 value: f32,
554 n: u32,
555};
556
557@group(0) @binding(1) var<uniform> uniforms: FillUniforms;
558
559@compute @workgroup_size(256)
560fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
561 let idx = global_id.x;
562 if idx >= uniforms.n { return; }
563 dst[idx] = uniforms.value;
564}
565"#;
566
567const REDUCE_SUM_WGSL: &str = r#"
576@group(0) @binding(0) var<storage, read> input: array<f32>;
577@group(0) @binding(1) var<storage, read_write> output: array<f32>;
578
579struct ReduceUniforms {
580 n: u32,
581};
582
583@group(0) @binding(2) var<uniform> uniforms: ReduceUniforms;
584
585var<workgroup> scratch: array<f32, 256>;
586
587@compute @workgroup_size(256)
588fn main(
589 @builtin(global_invocation_id) global_id: vec3<u32>,
590 @builtin(local_invocation_id) local_id: vec3<u32>,
591 @builtin(workgroup_id) wg_id: vec3<u32>,
592) {
593 let gidx = global_id.x;
594 let lidx = local_id.x;
595
596 // Load with bounds guard
597 if gidx < uniforms.n {
598 scratch[lidx] = input[gidx];
599 } else {
600 scratch[lidx] = 0.0;
601 }
602 workgroupBarrier();
603
604 // Tree reduction within the workgroup
605 var stride = 128u;
606 loop {
607 if stride == 0u { break; }
608 if lidx < stride {
609 scratch[lidx] += scratch[lidx + stride];
610 }
611 workgroupBarrier();
612 if stride == 1u { break; }
613 stride = stride >> 1u;
614 }
615
616 // Thread 0 writes the partial sum for this workgroup
617 if lidx == 0u {
618 output[wg_id.x] = scratch[0];
619 }
620}
621"#;
622
623const REDUCE_MAX_WGSL: &str = r#"
630@group(0) @binding(0) var<storage, read> input: array<f32>;
631@group(0) @binding(1) var<storage, read_write> output: array<f32>;
632
633struct ReduceUniforms {
634 n: u32,
635};
636
637@group(0) @binding(2) var<uniform> uniforms: ReduceUniforms;
638
639var<workgroup> scratch: array<f32, 256>;
640
641@compute @workgroup_size(256)
642fn main(
643 @builtin(global_invocation_id) global_id: vec3<u32>,
644 @builtin(local_invocation_id) local_id: vec3<u32>,
645 @builtin(workgroup_id) wg_id: vec3<u32>,
646) {
647 let gidx = global_id.x;
648 let lidx = local_id.x;
649
650 // Load with bounds guard; use -f32::MAX as neutral element for max
651 if gidx < uniforms.n {
652 scratch[lidx] = input[gidx];
653 } else {
654 scratch[lidx] = -3.402823e+38; // -FLT_MAX
655 }
656 workgroupBarrier();
657
658 // Tree reduction within the workgroup
659 var stride = 128u;
660 loop {
661 if stride == 0u { break; }
662 if lidx < stride {
663 scratch[lidx] = max(scratch[lidx], scratch[lidx + stride]);
664 }
665 workgroupBarrier();
666 if stride == 1u { break; }
667 stride = stride >> 1u;
668 }
669
670 if lidx == 0u {
671 output[wg_id.x] = scratch[0];
672 }
673}
674"#;
675
676const RK4_STAGE1_WGSL: &str = r#"
681@group(0) @binding(0) var<storage, read> y: array<f32>;
682@group(0) @binding(1) var<storage, read_write> k1: array<f32>;
683
684struct Rk4Uniforms {
685 t: f32,
686 h: f32,
687 n: u32,
688};
689
690@group(0) @binding(2) var<uniform> uniforms: Rk4Uniforms;
691
692@compute @workgroup_size(256)
693fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
694 let idx = global_id.x;
695 if idx >= uniforms.n { return; }
696 // Placeholder ODE: dy/dt = -y (exponential decay)
697 let dydt = -y[idx];
698 k1[idx] = uniforms.h * dydt;
699}
700"#;
701
702const RK4_STAGE2_WGSL: &str = r#"
707@group(0) @binding(0) var<storage, read> y: array<f32>;
708@group(0) @binding(1) var<storage, read> k1: array<f32>;
709@group(0) @binding(2) var<storage, read_write> k2: array<f32>;
710
711struct Rk4Uniforms {
712 t: f32,
713 h: f32,
714 n: u32,
715};
716
717@group(0) @binding(3) var<uniform> uniforms: Rk4Uniforms;
718
719@compute @workgroup_size(256)
720fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
721 let idx = global_id.x;
722 if idx >= uniforms.n { return; }
723 let y_mid = y[idx] + 0.5 * k1[idx];
724 // Placeholder ODE: dy/dt = -y
725 let dydt = -y_mid;
726 k2[idx] = uniforms.h * dydt;
727}
728"#;
729
730const RK4_STAGE3_WGSL: &str = r#"
735@group(0) @binding(0) var<storage, read> y: array<f32>;
736@group(0) @binding(1) var<storage, read> k2: array<f32>;
737@group(0) @binding(2) var<storage, read_write> k3: array<f32>;
738
739struct Rk4Uniforms {
740 t: f32,
741 h: f32,
742 n: u32,
743};
744
745@group(0) @binding(3) var<uniform> uniforms: Rk4Uniforms;
746
747@compute @workgroup_size(256)
748fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
749 let idx = global_id.x;
750 if idx >= uniforms.n { return; }
751 let y_mid = y[idx] + 0.5 * k2[idx];
752 // Placeholder ODE: dy/dt = -y
753 let dydt = -y_mid;
754 k3[idx] = uniforms.h * dydt;
755}
756"#;
757
758const RK4_STAGE4_WGSL: &str = r#"
763@group(0) @binding(0) var<storage, read> y: array<f32>;
764@group(0) @binding(1) var<storage, read> k3: array<f32>;
765@group(0) @binding(2) var<storage, read_write> k4: array<f32>;
766
767struct Rk4Uniforms {
768 t: f32,
769 h: f32,
770 n: u32,
771};
772
773@group(0) @binding(3) var<uniform> uniforms: Rk4Uniforms;
774
775@compute @workgroup_size(256)
776fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
777 let idx = global_id.x;
778 if idx >= uniforms.n { return; }
779 let y_next = y[idx] + k3[idx];
780 // Placeholder ODE: dy/dt = -y
781 let dydt = -y_next;
782 k4[idx] = uniforms.h * dydt;
783}
784"#;
785
786const RK4_COMBINE_WGSL: &str = r#"
792@group(0) @binding(0) var<storage, read> y: array<f32>;
793@group(0) @binding(1) var<storage, read> k1: array<f32>;
794@group(0) @binding(2) var<storage, read> k2: array<f32>;
795@group(0) @binding(3) var<storage, read> k3: array<f32>;
796@group(0) @binding(4) var<storage, read> k4: array<f32>;
797@group(0) @binding(5) var<storage, read_write> y_new: array<f32>;
798
799struct Rk4CombineUniforms {
800 n: u32,
801};
802
803@group(0) @binding(6) var<uniform> uniforms: Rk4CombineUniforms;
804
805@compute @workgroup_size(256)
806fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
807 let idx = global_id.x;
808 if idx >= uniforms.n { return; }
809 let weighted = k1[idx] + 2.0 * k2[idx] + 2.0 * k3[idx] + k4[idx];
810 y_new[idx] = y[idx] + weighted * (1.0 / 6.0);
811}
812"#;
813
814const ERROR_ESTIMATE_WGSL: &str = r#"
821@group(0) @binding(0) var<storage, read> y1: array<f32>;
822@group(0) @binding(1) var<storage, read> y2: array<f32>;
823@group(0) @binding(2) var<storage, read_write> err: array<f32>;
824
825struct ErrorUniforms {
826 rtol: f32,
827 atol: f32,
828 n: u32,
829};
830
831@group(0) @binding(3) var<uniform> uniforms: ErrorUniforms;
832
833@compute @workgroup_size(256)
834fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
835 let idx = global_id.x;
836 if idx >= uniforms.n { return; }
837
838 let v1 = y1[idx];
839 let v2 = y2[idx];
840 let abs_err = abs(v1 - v2);
841 let y_scale = max(abs(v1), abs(v2));
842 let scale = uniforms.atol + uniforms.rtol * y_scale;
843 err[idx] = abs_err / max(scale, 1e-7);
844}
845"#;
846
847fn create_rk4_stage1_kernel() -> BaseKernel {
851 let cuda_source = include_str!("rk4_stage1.cu");
852 let metadata = KernelMetadata {
853 workgroup_size: [256, 1, 1],
854 local_memory_usage: 0,
855 supports_tensor_cores: false,
856 operationtype: OperationType::ComputeIntensive,
857 backend_metadata: HashMap::new(),
858 };
859
860 BaseKernel::new(
861 "rk4_stage1",
862 cuda_source,
863 cuda_source, RK4_STAGE1_WGSL,
865 "", cuda_source, metadata,
868 )
869}
870
871fn create_rk4_stage2_kernel() -> BaseKernel {
873 let cuda_source = include_str!("rk4_stage2.cu");
874 let metadata = KernelMetadata {
875 workgroup_size: [256, 1, 1],
876 local_memory_usage: 0,
877 supports_tensor_cores: false,
878 operationtype: OperationType::ComputeIntensive,
879 backend_metadata: HashMap::new(),
880 };
881
882 BaseKernel::new(
883 "rk4_stage2",
884 cuda_source,
885 cuda_source,
886 RK4_STAGE2_WGSL,
887 "",
888 cuda_source,
889 metadata,
890 )
891}
892
893fn create_rk4_stage3_kernel() -> BaseKernel {
895 let cuda_source = include_str!("rk4_stage3.cu");
896 let metadata = KernelMetadata {
897 workgroup_size: [256, 1, 1],
898 local_memory_usage: 0,
899 supports_tensor_cores: false,
900 operationtype: OperationType::ComputeIntensive,
901 backend_metadata: HashMap::new(),
902 };
903
904 BaseKernel::new(
905 "rk4_stage3",
906 cuda_source,
907 cuda_source,
908 RK4_STAGE3_WGSL,
909 "",
910 cuda_source,
911 metadata,
912 )
913}
914
915fn create_rk4_stage4_kernel() -> BaseKernel {
917 let cuda_source = include_str!("rk4_stage4.cu");
918 let metadata = KernelMetadata {
919 workgroup_size: [256, 1, 1],
920 local_memory_usage: 0,
921 supports_tensor_cores: false,
922 operationtype: OperationType::ComputeIntensive,
923 backend_metadata: HashMap::new(),
924 };
925
926 BaseKernel::new(
927 "rk4_stage4",
928 cuda_source,
929 cuda_source,
930 RK4_STAGE4_WGSL,
931 "",
932 cuda_source,
933 metadata,
934 )
935}
936
937fn create_rk4_combine_kernel() -> BaseKernel {
939 let cuda_source = include_str!("rk4_combine.cu");
940 let metadata = KernelMetadata {
941 workgroup_size: [256, 1, 1],
942 local_memory_usage: 0,
943 supports_tensor_cores: false,
944 operationtype: OperationType::MemoryIntensive,
945 backend_metadata: HashMap::new(),
946 };
947
948 BaseKernel::new(
949 "rk4_combine",
950 cuda_source,
951 cuda_source,
952 RK4_COMBINE_WGSL,
953 "",
954 cuda_source,
955 metadata,
956 )
957}
958
959fn createerror_estimate_kernel() -> BaseKernel {
961 let cuda_source = include_str!("error_estimate.cu");
962 let metadata = KernelMetadata {
963 workgroup_size: [256, 1, 1],
964 local_memory_usage: 1024, supports_tensor_cores: false,
966 operationtype: OperationType::ComputeIntensive,
967 backend_metadata: HashMap::new(),
968 };
969
970 BaseKernel::new(
971 "error_estimate",
972 cuda_source,
973 cuda_source,
974 ERROR_ESTIMATE_WGSL,
975 "",
976 cuda_source,
977 metadata,
978 )
979}
980
981fn create_adam_optimizer_kernel() -> BaseKernel {
983 let cuda_source = include_str!("adam_optimizer.cu");
984 let metadata = KernelMetadata {
985 workgroup_size: [256, 1, 1],
986 local_memory_usage: 0,
987 supports_tensor_cores: false,
988 operationtype: OperationType::ComputeIntensive,
989 backend_metadata: HashMap::new(),
990 };
991
992 BaseKernel::new(
993 "adam_optimizer",
994 cuda_source,
995 cuda_source,
996 ADAM_WGSL,
997 "",
998 cuda_source,
999 metadata,
1000 )
1001}
1002
1003fn create_sgd_optimizer_kernel() -> BaseKernel {
1005 let cuda_source = include_str!("sgd_optimizer.cu");
1006 let metadata = KernelMetadata {
1007 workgroup_size: [256, 1, 1],
1008 local_memory_usage: 0,
1009 supports_tensor_cores: false,
1010 operationtype: OperationType::MemoryIntensive,
1011 backend_metadata: HashMap::new(),
1012 };
1013
1014 BaseKernel::new(
1015 "sgd_optimizer",
1016 cuda_source,
1017 cuda_source,
1018 SGD_WGSL,
1019 "",
1020 cuda_source,
1021 metadata,
1022 )
1023}
1024
1025fn create_rmsprop_optimizer_kernel() -> BaseKernel {
1027 let cuda_source = include_str!("rmsprop_optimizer.cu");
1028 let metadata = KernelMetadata {
1029 workgroup_size: [256, 1, 1],
1030 local_memory_usage: 0,
1031 supports_tensor_cores: false,
1032 operationtype: OperationType::ComputeIntensive,
1033 backend_metadata: HashMap::new(),
1034 };
1035
1036 BaseKernel::new(
1037 "rmsprop_optimizer",
1038 cuda_source,
1039 cuda_source,
1040 RMSPROP_WGSL,
1041 "",
1042 cuda_source,
1043 metadata,
1044 )
1045}
1046
1047fn create_adagrad_optimizer_kernel() -> BaseKernel {
1049 let cuda_source = include_str!("adagrad_optimizer.cu");
1050 let metadata = KernelMetadata {
1051 workgroup_size: [256, 1, 1],
1052 local_memory_usage: 0,
1053 supports_tensor_cores: false,
1054 operationtype: OperationType::ComputeIntensive,
1055 backend_metadata: HashMap::new(),
1056 };
1057
1058 BaseKernel::new(
1059 "adagrad_optimizer",
1060 cuda_source,
1061 cuda_source,
1062 ADAGRAD_WGSL,
1063 "",
1064 cuda_source,
1065 metadata,
1066 )
1067}
1068
1069fn create_lamb_optimizer_kernel() -> BaseKernel {
1071 let cuda_source = include_str!("lamb_optimizer.cu");
1072 let metadata = KernelMetadata {
1073 workgroup_size: [256, 1, 1],
1074 local_memory_usage: 0,
1075 supports_tensor_cores: false,
1076 operationtype: OperationType::ComputeIntensive,
1077 backend_metadata: HashMap::new(),
1078 };
1079
1080 BaseKernel::new(
1081 "lamb_optimizer",
1082 cuda_source,
1083 cuda_source,
1084 LAMB_WGSL,
1085 "",
1086 cuda_source,
1087 metadata,
1088 )
1089}
1090
1091fn create_memcpy_kernel() -> BaseKernel {
1093 let cuda_source = include_str!("memcpy.cu");
1094 let metadata = KernelMetadata {
1095 workgroup_size: [256, 1, 1],
1096 local_memory_usage: 0,
1097 supports_tensor_cores: false,
1098 operationtype: OperationType::MemoryIntensive,
1099 backend_metadata: HashMap::new(),
1100 };
1101
1102 BaseKernel::new(
1103 "memcpy",
1104 cuda_source,
1105 cuda_source,
1106 MEMCPY_WGSL,
1107 "",
1108 cuda_source,
1109 metadata,
1110 )
1111}
1112
1113fn create_fill_kernel() -> BaseKernel {
1115 let cuda_source = include_str!("fill.cu");
1116 let metadata = KernelMetadata {
1117 workgroup_size: [256, 1, 1],
1118 local_memory_usage: 0,
1119 supports_tensor_cores: false,
1120 operationtype: OperationType::MemoryIntensive,
1121 backend_metadata: HashMap::new(),
1122 };
1123
1124 BaseKernel::new(
1125 "fill",
1126 cuda_source,
1127 cuda_source,
1128 FILL_WGSL,
1129 "",
1130 cuda_source,
1131 metadata,
1132 )
1133}
1134
1135fn create_reduce_sum_kernel() -> BaseKernel {
1137 let cuda_source = include_str!("reduce_sum.cu");
1138 let metadata = KernelMetadata {
1139 workgroup_size: [256, 1, 1],
1140 local_memory_usage: 1024, supports_tensor_cores: false,
1142 operationtype: OperationType::ComputeIntensive,
1143 backend_metadata: HashMap::new(),
1144 };
1145
1146 BaseKernel::new(
1147 "reduce_sum",
1148 cuda_source,
1149 cuda_source,
1150 REDUCE_SUM_WGSL,
1151 "",
1152 cuda_source,
1153 metadata,
1154 )
1155}
1156
1157fn create_reduce_max_kernel() -> BaseKernel {
1159 let cuda_source = include_str!("reduce_max.cu");
1160 let metadata = KernelMetadata {
1161 workgroup_size: [256, 1, 1],
1162 local_memory_usage: 1024, supports_tensor_cores: false,
1164 operationtype: OperationType::ComputeIntensive,
1165 backend_metadata: HashMap::new(),
1166 };
1167
1168 BaseKernel::new(
1169 "reduce_max",
1170 cuda_source,
1171 cuda_source,
1172 REDUCE_MAX_WGSL,
1173 "",
1174 cuda_source,
1175 metadata,
1176 )
1177}