1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! The cascade: try the GPU, fall back to the CPU, always return an answer.
//!
//! This mirrors KOPITIAM's Offline-First pipeline (existing knowledge -> native
//! Rust -> local AI -> cloud AI). Here the same shape applies to compute:
//!
//! ```text
//! GPU (wgpu compute shader) -- fast path, used when a GPU is present
//! | Err / no adapter
//! v
//! CPU (pure Rust) -- correct path, always available
//! ```
//!
//! Two moving parts:
//!
//! * [`ComputeOp`] — an operation that knows how to do itself BOTH ways: a GPU
//! implementation (fallible — the GPU can be busy, out of memory, or absent)
//! and a CPU implementation (pure Rust, infallible — it is the floor the
//! cascade lands on).
//! * [`Executor`] — holds the cached [`GpuContext`] (or `None` if this machine
//! has no GPU) and runs the cascade: GPU first, CPU on any failure.
//!
//! Because the CPU path is a real, correct implementation and not a stub, the
//! guarantee is total: `Executor::run` returns the right answer on every
//! machine, GPU or not. On a no-GPU machine it simply never touches wgpu.
use crateGpuContext;
/// An operation implemented on BOTH the GPU and the CPU.
///
/// Implementors provide the two paths; the [`Executor`] chooses between them.
/// Keep `Input`/`Output` on plain Rust types (`&[f32]`, `Vec<f32>`, ...) so an
/// op is usable without pulling in wgpu types at the call site.
///
/// Contract the two paths MUST honour: for the same input, `compute_gpu` (when
/// it succeeds) and `compute_cpu` must produce the **same result** — same length
/// and, for floats, bit-for-bit equal for exactly-representable arithmetic like
/// elementwise add. The test suite asserts exactly this whenever a GPU is
/// present. If a kernel is only approximately equal to its CPU twin (e.g. a
/// fast-math reduction), say so in that op's docs and loosen its test to a
/// tolerance — do not weaken this trait's default expectation silently.
/// A GPU path failed to complete. The cascade treats ANY of these as "fall back
/// to CPU", so the variants exist for logging/diagnosis, not for the caller to
/// recover differently per case.
/// Runs [`ComputeOp`]s through the GPU->CPU cascade.
///
/// Build ONE and reuse it: it probes the GPU exactly once at construction and
/// caches the handle. A program that makes an `Executor` per call pays the
/// adapter-enumeration cost every time and defeats the caching.