dsh-eval-guard 0.7.2 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ISSUES.md +239 -0
- package/README.md +48 -18
- package/assets/neural-cifar/workspace.zip +0 -0
- package/assets/neural-cpp/workspace.zip +0 -0
- package/assets/neural-fp32/workspace.zip +0 -0
- package/assets/neural-pendulum/SPEC.md +43 -35
- package/assets/neural-pendulum/TASK.md +139 -33
- package/assets/neural-pendulum/rl-feasibility/README.md +60 -0
- package/assets/neural-pendulum/rl-feasibility/RESULTS.md +370 -0
- package/assets/neural-pendulum/rl-feasibility/evaluate.py +107 -0
- package/assets/neural-pendulum/rl-feasibility/finalize_run.py +168 -0
- package/assets/neural-pendulum/rl-feasibility/models.py +124 -0
- package/assets/neural-pendulum/rl-feasibility/obs.py +205 -0
- package/assets/neural-pendulum/rl-feasibility/plot_selected.py +55 -0
- package/assets/neural-pendulum/rl-feasibility/reference_controller.py +112 -0
- package/assets/neural-pendulum/rl-feasibility/results/curves_selected.png +0 -0
- package/assets/neural-pendulum/rl-feasibility/results/reference_controller.json +417 -0
- package/assets/neural-pendulum/rl-feasibility/results/summary.json +1599 -0
- package/assets/neural-pendulum/rl-feasibility/results/table.md +39 -0
- package/assets/neural-pendulum/rl-feasibility/sim.py +324 -0
- package/assets/neural-pendulum/rl-feasibility/summarize.py +175 -0
- package/assets/neural-pendulum/rl-feasibility/task.py +342 -0
- package/assets/neural-pendulum/rl-feasibility/test_contract.py +188 -0
- package/assets/neural-pendulum/rl-feasibility/train_ppo.py +403 -0
- package/assets/neural-pendulum/rl-feasibility/train_sac.py +406 -0
- package/assets/neural-pendulum/sim.cpp +13 -2
- package/assets/neural-pendulum/sim_eval +0 -0
- package/assets/neural-pendulum/workspace.zip +0 -0
- package/eval/README.md +19 -9
- package/eval/bomberman.py +5 -3
- package/eval/commit0.py +10 -3
- package/eval/common.py +169 -5
- package/eval/ctf.py +4 -2
- package/eval/featurebench.py +12 -8
- package/eval/land.py +4 -2
- package/eval/legacy/bomberman.py +5 -2
- package/eval/legacy/ctf.py +5 -2
- package/eval/legacy/featurebench.py +55 -15
- package/eval/legacy/land.py +6 -3
- package/eval/legacy/swe_bench_pro.py +57 -16
- package/eval/legacy/tank.py +2 -2
- package/eval/legacy/warehouse.py +4 -4
- package/eval/neural-cpp.py +9 -6
- package/eval/neural-fp32.py +17 -5
- package/eval/swe-bench-pro.py +11 -7
- package/eval/tank.py +11 -2
- package/eval/warehouse.py +17 -1
- package/lib/client/index.js +56 -29
- package/lib/client/index.js.map +1 -1
- package/lib/index.js +883 -298
- package/native/dsh-eval-supervisor +0 -0
- package/native/supervisor.c +232 -36
- package/neural-cifar-eval/README.md +5 -0
- package/neural-cifar-eval/common.py +13 -0
- package/neural-cifar-eval/ops_eval.py +17 -5
- package/neural-cifar-eval/run_eval.py +42 -32
- package/neural-pendulum-eval/README.md +62 -0
- package/neural-pendulum-eval/ops_eval.py +603 -0
- package/neural-pendulum-eval/run_eval.py +218 -137
- package/neural-pendulum-eval/sim_eval +0 -0
- package/package.json +7 -11
- package/assets/neural-pendulum/hidden/test_infra.cpp +0 -631
- package/assets/neural-pendulum/include/nn/nn.hpp +0 -88
|
@@ -1,631 +0,0 @@
|
|
|
1
|
-
#include <nn/nn.hpp>
|
|
2
|
-
|
|
3
|
-
#include <algorithm>
|
|
4
|
-
#include <chrono>
|
|
5
|
-
#include <cmath>
|
|
6
|
-
#include <cstdint>
|
|
7
|
-
#include <cstring>
|
|
8
|
-
#include <cstdio>
|
|
9
|
-
#include <functional>
|
|
10
|
-
#include <random>
|
|
11
|
-
#include <string>
|
|
12
|
-
#include <thread>
|
|
13
|
-
#include <vector>
|
|
14
|
-
|
|
15
|
-
using nn::DType;
|
|
16
|
-
using nn::Shape;
|
|
17
|
-
using nn::Tensor;
|
|
18
|
-
|
|
19
|
-
static int g_passed = 0;
|
|
20
|
-
static int g_failed = 0;
|
|
21
|
-
|
|
22
|
-
static void report(const std::string& name, bool ok) {
|
|
23
|
-
if (ok) { ++g_passed; std::printf("TEST %s PASS\n", name.c_str()); }
|
|
24
|
-
else { ++g_failed; std::printf("TEST %s FAIL\n", name.c_str()); }
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
static bool close(float a, float b, float tol = 1e-4f) {
|
|
28
|
-
return std::fabs(a - b) <= tol * (1.0f + std::fabs(a) + std::fabs(b));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static std::vector<float> f32_data(const Tensor& t) {
|
|
32
|
-
Tensor c = t.contiguous();
|
|
33
|
-
std::vector<float> out(static_cast<size_t>(c.numel()));
|
|
34
|
-
if (out.empty()) return out;
|
|
35
|
-
std::memcpy(out.data(), c.data(), out.size() * sizeof(float));
|
|
36
|
-
return out;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static Tensor make_f32(const Shape& shape, const std::vector<float>& values) {
|
|
40
|
-
return Tensor::from_data(values.data(), shape, DType::F32);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static bool eq_data(const Tensor& t, const std::vector<float>& expected, float tol = 1e-4f) {
|
|
44
|
-
const std::vector<float> got = f32_data(t);
|
|
45
|
-
if (got.size() != expected.size()) return false;
|
|
46
|
-
for (size_t i = 0; i < got.size(); ++i) if (!close(got[i], expected[i], tol)) return false;
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
static bool shape_is(const Tensor& t, const Shape& shape) { return t.shape() == shape; }
|
|
51
|
-
|
|
52
|
-
static void test_dtype_metadata() {
|
|
53
|
-
bool ok = nn::dtype_size(DType::F32) == 4 && nn::dtype_size(DType::F64) == 8 &&
|
|
54
|
-
nn::dtype_size(DType::I8) == 1 && nn::dtype_size(DType::I16) == 2 &&
|
|
55
|
-
nn::dtype_size(DType::I32) == 4 && nn::dtype_size(DType::I64) == 8 &&
|
|
56
|
-
nn::dtype_size(DType::I128) == 16 && nn::dtype_size(DType::U128) == 16 &&
|
|
57
|
-
nn::dtype_size(DType::BF16) == 2 && nn::dtype_size(DType::FP8_E5M2) == 1 &&
|
|
58
|
-
nn::dtype_size(DType::MXFP4) == 1;
|
|
59
|
-
report("dtype_metadata", ok);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
static void test_casts_float() {
|
|
63
|
-
Tensor a = make_f32({3}, {1.5f, -2.25f, 3.0f});
|
|
64
|
-
Tensor d = a.to(DType::F64);
|
|
65
|
-
Tensor back = d.to(DType::F32);
|
|
66
|
-
report("cast_float", d.dtype() == DType::F64 && eq_data(back, {1.5f, -2.25f, 3.0f}));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
static void test_casts_int() {
|
|
70
|
-
Tensor a = make_f32({5}, {3.6f, -1.2f, 300.0f, -300.0f, 0.0f});
|
|
71
|
-
Tensor i = a.to(DType::I32);
|
|
72
|
-
Tensor narrow = a.to(DType::I8);
|
|
73
|
-
int32_t iv[5]{};
|
|
74
|
-
int8_t nv[5]{};
|
|
75
|
-
std::memcpy(iv, i.contiguous().data(), sizeof(iv));
|
|
76
|
-
std::memcpy(nv, narrow.contiguous().data(), sizeof(nv));
|
|
77
|
-
bool ok = iv[0] == 4 && iv[1] == -1 && iv[2] == 300 && iv[3] == -300 && iv[4] == 0;
|
|
78
|
-
ok = ok && nv[0] == 4 && nv[1] == -1 && nv[2] == 127 && nv[3] == -128 && nv[4] == 0;
|
|
79
|
-
report("cast_int_saturate", ok);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
static void test_integer_casts() {
|
|
83
|
-
Tensor a = make_f32({4}, {0.0f, 1.0f, 2.0f, 3.0f});
|
|
84
|
-
bool ok = true;
|
|
85
|
-
for (DType d : {DType::I8, DType::I16, DType::I32, DType::I64, DType::I128,
|
|
86
|
-
DType::U8, DType::U16, DType::U32, DType::U64, DType::U128}) {
|
|
87
|
-
Tensor back = a.to(d).to(DType::F32);
|
|
88
|
-
ok = ok && eq_data(back, {0.0f, 1.0f, 2.0f, 3.0f});
|
|
89
|
-
}
|
|
90
|
-
report("integer_casts", ok);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
static void test_low_precision_casts() {
|
|
94
|
-
Tensor a = make_f32({4}, {1.5f, -2.0f, 0.5f, 0.0f});
|
|
95
|
-
Tensor bf = a.to(DType::BF16).to(DType::F32);
|
|
96
|
-
Tensor fp8 = a.to(DType::FP8_E5M2).to(DType::F32);
|
|
97
|
-
Tensor mx = make_f32({32}, std::vector<float>(32, 1.0f)).to(DType::MXFP4).to(DType::F32);
|
|
98
|
-
bool ok = eq_data(bf, {1.5f, -2.0f, 0.5f, 0.0f}, 0.01f);
|
|
99
|
-
ok = ok && eq_data(fp8, {1.5f, -2.0f, 0.5f, 0.0f}, 0.01f);
|
|
100
|
-
ok = ok && eq_data(mx, std::vector<float>(32, 1.0f), 0.01f);
|
|
101
|
-
report("low_precision_casts", ok);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
static void test_views() {
|
|
105
|
-
std::vector<float> v(24);
|
|
106
|
-
for (int i = 0; i < 24; ++i) v[i] = static_cast<float>(i);
|
|
107
|
-
Tensor a = make_f32({2, 3, 4}, v);
|
|
108
|
-
Tensor p = a.permute({2, 0, 1});
|
|
109
|
-
bool ok = shape_is(p, {4, 2, 3});
|
|
110
|
-
const std::vector<float> pv = f32_data(p);
|
|
111
|
-
ok = ok && pv.size() == 24 && close(pv[0], 0.0f) && close(pv[1], 4.0f) && close(pv[2], 8.0f);
|
|
112
|
-
Tensor c = a.reshape({6, 4});
|
|
113
|
-
ok = ok && shape_is(c, {6, 4}) && eq_data(c, v);
|
|
114
|
-
report("views_permute_reshape", ok);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
static void test_slices() {
|
|
118
|
-
std::vector<float> v(10);
|
|
119
|
-
for (int i = 0; i < 10; ++i) v[i] = static_cast<float>(i);
|
|
120
|
-
Tensor a = make_f32({10}, v);
|
|
121
|
-
Tensor s = a.slice(0, 1, 8, 2);
|
|
122
|
-
Tensor r = a.slice(0, 8, 1, -2);
|
|
123
|
-
bool ok = eq_data(s, {1, 3, 5, 7}) && eq_data(r, {8, 6, 4, 2});
|
|
124
|
-
report("slices_negative_step", ok);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
static void test_elementwise_broadcast() {
|
|
128
|
-
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6});
|
|
129
|
-
Tensor b = make_f32({3}, {10, 20, 30});
|
|
130
|
-
Tensor c = nn::add(a, b);
|
|
131
|
-
Tensor d = nn::mul(c, b);
|
|
132
|
-
bool ok = shape_is(c, {2, 3}) && eq_data(c, {11, 22, 33, 14, 25, 36});
|
|
133
|
-
ok = ok && eq_data(d, {110, 440, 990, 140, 500, 1080});
|
|
134
|
-
report("elementwise_broadcast", ok);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
static void test_reductions() {
|
|
138
|
-
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6});
|
|
139
|
-
Tensor s = nn::sum(a, 1);
|
|
140
|
-
Tensor m = nn::mean(a, -1);
|
|
141
|
-
report("reductions", eq_data(s, {6, 15}) && close(f32_data(m)[0], 3.5f));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
static void test_matmul_2d() {
|
|
145
|
-
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6});
|
|
146
|
-
Tensor b = make_f32({3, 2}, {7, 8, 9, 10, 11, 12});
|
|
147
|
-
Tensor c = nn::matmul(a, b);
|
|
148
|
-
report("matmul_2d", shape_is(c, {2, 2}) && eq_data(c, {58, 64, 139, 154}));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
static void test_matmul_batch_and_nd() {
|
|
152
|
-
Tensor a = make_f32({2, 2, 3}, {1, 2, 3, 4, 5, 6, 1, 0, 0, 0, 1, 0});
|
|
153
|
-
Tensor b = make_f32({2, 3, 2}, {1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0});
|
|
154
|
-
Tensor c = nn::matmul(a, b);
|
|
155
|
-
bool ok = shape_is(c, {2, 2, 2}) && eq_data(c, {1, 2, 4, 5, 1, 0, 0, 1});
|
|
156
|
-
Tensor a2 = make_f32({2, 3, 4}, std::vector<float>(24, 1.0f));
|
|
157
|
-
Tensor b2 = make_f32({2, 4, 5}, std::vector<float>(40, 1.0f));
|
|
158
|
-
Tensor c2 = nn::matmul_nd(a2, b2, {0}, {0}, {1, 2}, {1, 2});
|
|
159
|
-
ok = ok && shape_is(c2, {2, 3, 5}) && eq_data(c2, std::vector<float>(30, 4.0f));
|
|
160
|
-
report("matmul_batch_nd", ok);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
static void test_autograd_add_mul() {
|
|
164
|
-
Tensor a = make_f32({2}, {2.0f, 3.0f}); a.set_requires_grad(true);
|
|
165
|
-
Tensor b = make_f32({2}, {5.0f, 7.0f}); b.set_requires_grad(true);
|
|
166
|
-
Tensor c = nn::add(nn::mul(a, b), a);
|
|
167
|
-
nn::sum(c).backward();
|
|
168
|
-
bool ok = eq_data(a.grad(), {6.0f, 8.0f}) && eq_data(b.grad(), {2.0f, 3.0f});
|
|
169
|
-
report("autograd_add_mul", ok);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
static void test_autograd_matmul() {
|
|
173
|
-
Tensor a = make_f32({2, 3}, {1, 2, 3, 4, 5, 6}); a.set_requires_grad(true);
|
|
174
|
-
Tensor b = make_f32({3, 2}, {7, 8, 9, 10, 11, 12}); b.set_requires_grad(true);
|
|
175
|
-
nn::sum(nn::matmul(a, b)).backward();
|
|
176
|
-
bool ok = eq_data(a.grad(), {15, 19, 23, 15, 19, 23});
|
|
177
|
-
ok = ok && eq_data(b.grad(), {5, 5, 7, 7, 9, 9});
|
|
178
|
-
report("autograd_matmul", ok);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
static void test_autograd_view_slice() {
|
|
182
|
-
Tensor x = make_f32({2, 3}, {1, 2, 3, 4, 5, 6}); x.set_requires_grad(true);
|
|
183
|
-
Tensor s = x.slice(1, 0, 2);
|
|
184
|
-
nn::sum(s).backward();
|
|
185
|
-
report("autograd_slice", eq_data(x.grad(), {1, 1, 0, 1, 1, 0}));
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
static void test_stochastic_stats() {
|
|
189
|
-
const float lo = 1.0f;
|
|
190
|
-
const float hi = 1.0078125f; // bf16 adjacent around 1.0
|
|
191
|
-
const float mid = (lo + hi) * 0.5f;
|
|
192
|
-
std::vector<float> vals(4096, mid);
|
|
193
|
-
Tensor a = make_f32({4096}, vals);
|
|
194
|
-
Tensor q = a.to(DType::BF16, nn::Rounding::Stochastic, 12345);
|
|
195
|
-
Tensor f = q.to(DType::F32);
|
|
196
|
-
const std::vector<float> out = f32_data(f);
|
|
197
|
-
int upper = 0;
|
|
198
|
-
for (float v : out) { if (v > mid) ++upper; }
|
|
199
|
-
report("stochastic_stats", upper > 1500 && upper < 2600);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
static void test_threads() {
|
|
203
|
-
nn::set_thread_mode(nn::ThreadMode::Development);
|
|
204
|
-
nn::set_num_threads(4);
|
|
205
|
-
int dev = nn::active_workers();
|
|
206
|
-
bool ok = dev >= 1 && dev <= nn::kDevMaxThreads;
|
|
207
|
-
nn::set_thread_mode(nn::ThreadMode::Evaluation);
|
|
208
|
-
nn::set_num_threads(0);
|
|
209
|
-
ok = ok && nn::active_workers() >= 1;
|
|
210
|
-
report("thread_policy", ok);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
static void test_all_dtype_alloc() {
|
|
214
|
-
bool ok = true;
|
|
215
|
-
for (DType d : {DType::F32, DType::F64, DType::I8, DType::I16, DType::I32, DType::I64,
|
|
216
|
-
DType::I128, DType::U8, DType::U16, DType::U32, DType::U64, DType::U128,
|
|
217
|
-
DType::BF16, DType::FP8_E5M2, DType::MXFP4}) {
|
|
218
|
-
Tensor t = Tensor::empty(d == DType::MXFP4 ? Shape{32} : Shape{2, 3}, d);
|
|
219
|
-
ok = ok && t.numel() == (d == DType::MXFP4 ? 32 : 6) && t.dtype() == d;
|
|
220
|
-
}
|
|
221
|
-
report("all_dtype_alloc", ok);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
static void bench_matmul() {
|
|
225
|
-
const int n = 256;
|
|
226
|
-
std::vector<float> av(static_cast<size_t>(n) * n), bv(static_cast<size_t>(n) * n);
|
|
227
|
-
for (size_t i = 0; i < av.size(); ++i) { av[i] = static_cast<float>((i * 17) % 101) * 0.01f; bv[i] = static_cast<float>((i * 29) % 97) * 0.01f; }
|
|
228
|
-
Tensor a = make_f32({n, n}, av);
|
|
229
|
-
Tensor b = make_f32({n, n}, bv);
|
|
230
|
-
nn::set_thread_mode(nn::ThreadMode::Evaluation);
|
|
231
|
-
nn::set_num_threads(0);
|
|
232
|
-
Tensor warm = nn::matmul(a, b);
|
|
233
|
-
(void)warm;
|
|
234
|
-
const int iters = 3;
|
|
235
|
-
auto start = std::chrono::steady_clock::now();
|
|
236
|
-
for (int i = 0; i < iters; ++i) { Tensor c = nn::matmul(a, b); (void)c; }
|
|
237
|
-
auto end = std::chrono::steady_clock::now();
|
|
238
|
-
double ms = std::chrono::duration<double, std::milli>(end - start).count() / iters;
|
|
239
|
-
double gflops = (2.0 * n * n * n) / (ms * 1e6);
|
|
240
|
-
std::printf("PERF_MS %.6f\nPERF_GFLOPS %.6f\n", ms, gflops);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
// ---------------------------------------------------------------------------
|
|
245
|
-
// Metric section. Reference values are computed by local scalar reference code
|
|
246
|
-
// BEFORE calling the candidate implementation. Candidate timing only wraps
|
|
247
|
-
// candidate calls; reference loops are never inside the timed region.
|
|
248
|
-
// ---------------------------------------------------------------------------
|
|
249
|
-
|
|
250
|
-
static std::vector<float> ref_matmul_f32(const std::vector<float>& a, const std::vector<float>& b,
|
|
251
|
-
int M, int K, int N) {
|
|
252
|
-
std::vector<float> c(static_cast<size_t>(M) * N, 0.0f);
|
|
253
|
-
for (int i = 0; i < M; ++i)
|
|
254
|
-
for (int k = 0; k < K; ++k)
|
|
255
|
-
for (int j = 0; j < N; ++j)
|
|
256
|
-
c[static_cast<size_t>(i) * N + j] += a[static_cast<size_t>(i) * K + k] * b[static_cast<size_t>(k) * N + j];
|
|
257
|
-
return c;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
static const float kMxTable[8] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f};
|
|
261
|
-
|
|
262
|
-
static float mx_quant_one(float x, float scale, std::mt19937_64* rng) {
|
|
263
|
-
const float q = x / scale;
|
|
264
|
-
const float aq = std::fabs(q);
|
|
265
|
-
int code = 0;
|
|
266
|
-
if (aq >= kMxTable[7]) {
|
|
267
|
-
code = 7;
|
|
268
|
-
} else {
|
|
269
|
-
int lo = 0, hi = 1;
|
|
270
|
-
for (int c = 0; c < 7; ++c) if (kMxTable[c] <= aq && aq <= kMxTable[c + 1]) { lo = c; hi = c + 1; break; }
|
|
271
|
-
const float t = (aq - kMxTable[lo]) / (kMxTable[hi] - kMxTable[lo]);
|
|
272
|
-
if (rng != nullptr && t > 0.0f && t < 1.0f) {
|
|
273
|
-
std::uniform_real_distribution<double> d(0.0, 1.0);
|
|
274
|
-
code = d(*rng) < t ? hi : lo;
|
|
275
|
-
} else {
|
|
276
|
-
code = t < 0.5f ? lo : hi;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
const float v = kMxTable[code] * scale;
|
|
280
|
-
return q < 0 ? -v : v;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
static std::vector<float> mx_quantize(const std::vector<float>& x, std::mt19937_64* rng) {
|
|
284
|
-
std::vector<float> out(x.size());
|
|
285
|
-
for (size_t base = 0; base < x.size(); base += 32) {
|
|
286
|
-
float mx = 0.0f;
|
|
287
|
-
for (size_t j = base; j < std::min(x.size(), base + 32); ++j) mx = std::max(mx, std::fabs(x[j]));
|
|
288
|
-
int e = 127;
|
|
289
|
-
if (mx > 0) e = static_cast<int>(std::floor(std::log2(mx / 4.0f))) + 127;
|
|
290
|
-
e = std::max(0, std::min(254, e));
|
|
291
|
-
const float scale = std::pow(2.0f, e - 127);
|
|
292
|
-
for (size_t j = base; j < std::min(x.size(), base + 32); ++j) out[j] = mx_quant_one(x[j], scale, rng);
|
|
293
|
-
}
|
|
294
|
-
return out;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
static std::vector<float> ref_matmul_mx(const std::vector<float>& a, const std::vector<float>& b,
|
|
298
|
-
int M, int K, int N, std::mt19937_64* rng) {
|
|
299
|
-
std::vector<float> aq = mx_quantize(a, rng), bq = mx_quantize(b, rng);
|
|
300
|
-
std::vector<float> c = ref_matmul_f32(aq, bq, M, K, N);
|
|
301
|
-
return mx_quantize(c, rng);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
static std::vector<__int128> ref_matmul_i128(const std::vector<__int128>& a,
|
|
305
|
-
const std::vector<__int128>& b, int M, int K, int N) {
|
|
306
|
-
std::vector<__int128> c(static_cast<size_t>(M) * N, 0);
|
|
307
|
-
for (int i = 0; i < M; ++i)
|
|
308
|
-
for (int k = 0; k < K; ++k)
|
|
309
|
-
for (int j = 0; j < N; ++j)
|
|
310
|
-
c[static_cast<size_t>(i) * N + j] += a[static_cast<size_t>(i) * K + k] * b[static_cast<size_t>(k) * N + j];
|
|
311
|
-
return c;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
static double mean_abs_error_f32(const std::vector<float>& got, const std::vector<float>& ref) {
|
|
315
|
-
double s = 0.0;
|
|
316
|
-
for (size_t i = 0; i < got.size(); ++i) s += std::fabs(static_cast<double>(got[i]) - ref[i]);
|
|
317
|
-
return got.empty() ? 0.0 : s / got.size();
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
static double mean_abs_error_i128(const std::vector<__int128>& got, const std::vector<__int128>& ref) {
|
|
321
|
-
double s = 0.0;
|
|
322
|
-
for (size_t i = 0; i < got.size(); ++i) {
|
|
323
|
-
__int128 d = got[i] - ref[i];
|
|
324
|
-
if (d < 0) d = -d;
|
|
325
|
-
s += static_cast<double>(d);
|
|
326
|
-
}
|
|
327
|
-
return got.empty() ? 0.0 : s / got.size();
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
static std::vector<__int128> read_i128(const Tensor& t) {
|
|
331
|
-
Tensor c = t.contiguous();
|
|
332
|
-
std::vector<__int128> out(static_cast<size_t>(c.numel()), 0);
|
|
333
|
-
if (c.dtype() != DType::I128) return out;
|
|
334
|
-
std::memcpy(out.data(), c.data(), out.size() * sizeof(__int128));
|
|
335
|
-
return out;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
static void emit_metric(const char* dtype, int stochastic, int M, int K, int N,
|
|
339
|
-
double fwd_acc, double fwd_err, double fwd_ms,
|
|
340
|
-
double bwd_acc, double bwd_err, double bwd_ms) {
|
|
341
|
-
const double ops = 2.0 * M * K * N;
|
|
342
|
-
const double fwd_gflops = fwd_ms > 0 ? ops / (fwd_ms * 1e6) : -1.0;
|
|
343
|
-
const double bwd_gflops = bwd_ms > 0 ? ops / (bwd_ms * 1e6) : -1.0;
|
|
344
|
-
std::printf("METRIC dtype=%s stochastic=%d m=%d k=%d n=%d fwd_accuracy=%.6f fwd_mean_err=%.9g fwd_ms=%.6f fwd_gflops=%.6f bwd_accuracy=%.6f bwd_mean_err=%.9g bwd_ms=%.6f bwd_gflops=%.6f\n",
|
|
345
|
-
dtype, stochastic, M, K, N, fwd_acc, fwd_err, fwd_ms, fwd_gflops,
|
|
346
|
-
bwd_acc, bwd_err, bwd_ms, bwd_gflops);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
static double time_once_ms(const std::function<void()>& fn, int iters = 3) {
|
|
350
|
-
// warmup
|
|
351
|
-
fn();
|
|
352
|
-
auto start = std::chrono::steady_clock::now();
|
|
353
|
-
for (int i = 0; i < iters; ++i) fn();
|
|
354
|
-
auto end = std::chrono::steady_clock::now();
|
|
355
|
-
return std::chrono::duration<double, std::milli>(end - start).count() / iters;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
static void fill_rand(std::vector<float>& v, uint64_t seed, float lo, float hi) {
|
|
359
|
-
std::mt19937_64 rng(seed);
|
|
360
|
-
std::uniform_real_distribution<float> d(lo, hi);
|
|
361
|
-
for (float& x : v) x = d(rng);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
struct StatScore {
|
|
365
|
-
double accuracy = 0.0;
|
|
366
|
-
double mean_err = 0.0;
|
|
367
|
-
double std_ratio = 0.0;
|
|
368
|
-
double ref_mean_avg = 0.0;
|
|
369
|
-
double ref_std_avg = 0.0;
|
|
370
|
-
double cand_mean_avg = 0.0;
|
|
371
|
-
double cand_std_avg = 0.0;
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
static void add_stats(std::vector<double>& sum, std::vector<double>& sq, const std::vector<float>& v) {
|
|
375
|
-
for (size_t i = 0; i < v.size(); ++i) {
|
|
376
|
-
sum[i] += v[i];
|
|
377
|
-
sq[i] += static_cast<double>(v[i]) * v[i];
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
static StatScore score_stats(const std::vector<double>& ref_sum, const std::vector<double>& ref_sq,
|
|
382
|
-
const std::vector<double>& cand_sum, const std::vector<double>& cand_sq,
|
|
383
|
-
int samples) {
|
|
384
|
-
StatScore out;
|
|
385
|
-
const double n = std::max(1, samples);
|
|
386
|
-
int ok = 0;
|
|
387
|
-
for (size_t i = 0; i < ref_sum.size(); ++i) {
|
|
388
|
-
const double rm = ref_sum[i] / n;
|
|
389
|
-
const double rv = std::max(0.0, ref_sq[i] / n - rm * rm);
|
|
390
|
-
const double rs = std::sqrt(rv);
|
|
391
|
-
const double cm = cand_sum[i] / n;
|
|
392
|
-
const double cv = std::max(0.0, cand_sq[i] / n - cm * cm);
|
|
393
|
-
const double cs = std::sqrt(cv);
|
|
394
|
-
bool good = false;
|
|
395
|
-
if (rs <= 1e-12) good = std::fabs(cm - rm) <= 1e-6 && cs <= 1e-6;
|
|
396
|
-
else good = std::fabs(cm - rm) <= 3.0 * rs && cs >= 0.1 * rs && cs <= 10.0 * rs;
|
|
397
|
-
if (good) ++ok;
|
|
398
|
-
out.mean_err += std::fabs(cm - rm);
|
|
399
|
-
out.std_ratio += (rs > 1e-12) ? cs / rs : 1.0;
|
|
400
|
-
out.ref_mean_avg += rm;
|
|
401
|
-
out.ref_std_avg += rs;
|
|
402
|
-
out.cand_mean_avg += cm;
|
|
403
|
-
out.cand_std_avg += cs;
|
|
404
|
-
}
|
|
405
|
-
const double count = static_cast<double>(ref_sum.size());
|
|
406
|
-
out.accuracy = 100.0 * ok / count;
|
|
407
|
-
out.mean_err /= count;
|
|
408
|
-
out.std_ratio /= count;
|
|
409
|
-
out.ref_mean_avg /= count;
|
|
410
|
-
out.ref_std_avg /= count;
|
|
411
|
-
out.cand_mean_avg /= count;
|
|
412
|
-
out.cand_std_avg /= count;
|
|
413
|
-
return out;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
static void metric_f32() {
|
|
417
|
-
const int M = 256, K = 256, N = 256;
|
|
418
|
-
const int DATA = 4;
|
|
419
|
-
double acc_f = 0.0, err_f = 0.0, ms_f = 0.0, acc_b = 0.0, err_b = 0.0, ms_b = 0.0;
|
|
420
|
-
for (int d = 0; d < DATA; ++d) {
|
|
421
|
-
std::vector<float> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
422
|
-
fill_rand(a, 1000 + d, -1.0f, 1.0f);
|
|
423
|
-
fill_rand(b, 2000 + d, -1.0f, 1.0f);
|
|
424
|
-
const std::vector<float> ref_c = ref_matmul_f32(a, b, M, K, N);
|
|
425
|
-
std::vector<float> ref_da(static_cast<size_t>(M) * K), ref_db(static_cast<size_t>(K) * N);
|
|
426
|
-
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { float s = 0; for (int j = 0; j < N; ++j) s += b[k * N + j]; ref_da[i * K + k] = s; }
|
|
427
|
-
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { float s = 0; for (int i = 0; i < M; ++i) s += a[i * K + k]; ref_db[k * N + j] = s; }
|
|
428
|
-
|
|
429
|
-
Tensor at = make_f32({M, K}, a), bt = make_f32({K, N}, b);
|
|
430
|
-
const std::vector<float> got = f32_data(nn::matmul(at, bt));
|
|
431
|
-
double err = mean_abs_error_f32(got, ref_c);
|
|
432
|
-
int ok = 0; for (size_t i = 0; i < got.size(); ++i) if (std::fabs(got[i] - ref_c[i]) <= 1e-3f + 1e-4f * std::fabs(ref_c[i])) ++ok;
|
|
433
|
-
acc_f += 100.0 * ok / got.size(); err_f += err;
|
|
434
|
-
ms_f += time_once_ms([&] { Tensor c = nn::matmul(at, bt); (void)c; });
|
|
435
|
-
|
|
436
|
-
Tensor ag = make_f32({M, K}, a), bg = make_f32({K, N}, b);
|
|
437
|
-
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
438
|
-
ms_b += time_once_ms([&] {
|
|
439
|
-
ag = make_f32({M, K}, a); bg = make_f32({K, N}, b);
|
|
440
|
-
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
441
|
-
Tensor c = nn::matmul(ag, bg);
|
|
442
|
-
nn::sum(c).backward();
|
|
443
|
-
});
|
|
444
|
-
const std::vector<float> got_da = f32_data(ag.grad()), got_db = f32_data(bg.grad());
|
|
445
|
-
double err_da = mean_abs_error_f32(got_da, ref_da), err_db = mean_abs_error_f32(got_db, ref_db);
|
|
446
|
-
int ok_da = 0, ok_db = 0;
|
|
447
|
-
for (size_t i = 0; i < got_da.size(); ++i) if (std::fabs(got_da[i] - ref_da[i]) <= 1e-3f) ++ok_da;
|
|
448
|
-
for (size_t i = 0; i < got_db.size(); ++i) if (std::fabs(got_db[i] - ref_db[i]) <= 1e-3f) ++ok_db;
|
|
449
|
-
acc_b += 100.0 * (ok_da + ok_db) / (got_da.size() + got_db.size());
|
|
450
|
-
err_b += (err_da + err_db) / 2.0;
|
|
451
|
-
}
|
|
452
|
-
emit_metric("f32", 0, M, K, N, acc_f / DATA, err_f / DATA, ms_f / DATA, acc_b / DATA, err_b / DATA, ms_b / DATA);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
static void metric_i128() {
|
|
456
|
-
const int M = 256, K = 256, N = 256;
|
|
457
|
-
const int DATA = 4;
|
|
458
|
-
double acc_f = 0.0, err_f = 0.0, ms_f = 0.0, acc_b = 0.0, err_b = 0.0, ms_b = 0.0;
|
|
459
|
-
for (int d = 0; d < DATA; ++d) {
|
|
460
|
-
std::vector<__int128> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
461
|
-
for (size_t i = 0; i < a.size(); ++i) a[i] = static_cast<int>((i * 17 + d * 13) % 9) - 4;
|
|
462
|
-
for (size_t i = 0; i < b.size(); ++i) b[i] = static_cast<int>((i * 29 + d * 7) % 9) - 4;
|
|
463
|
-
const std::vector<__int128> ref_c = ref_matmul_i128(a, b, M, K, N);
|
|
464
|
-
std::vector<__int128> ref_da(static_cast<size_t>(M) * K), ref_db(static_cast<size_t>(K) * N);
|
|
465
|
-
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { __int128 s = 0; for (int j = 0; j < N; ++j) s += b[k * N + j]; ref_da[i * K + k] = s; }
|
|
466
|
-
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { __int128 s = 0; for (int i = 0; i < M; ++i) s += a[i * K + k]; ref_db[k * N + j] = s; }
|
|
467
|
-
|
|
468
|
-
Tensor at = Tensor::from_data(a.data(), {M, K}, DType::I128);
|
|
469
|
-
Tensor bt = Tensor::from_data(b.data(), {K, N}, DType::I128);
|
|
470
|
-
const std::vector<__int128> got = read_i128(nn::matmul(at, bt));
|
|
471
|
-
double err = mean_abs_error_i128(got, ref_c);
|
|
472
|
-
int ok = 0; for (size_t i = 0; i < got.size(); ++i) if (got[i] == ref_c[i]) ++ok;
|
|
473
|
-
acc_f += 100.0 * ok / got.size(); err_f += err;
|
|
474
|
-
ms_f += time_once_ms([&] { Tensor c = nn::matmul(at, bt); (void)c; });
|
|
475
|
-
|
|
476
|
-
Tensor ag = Tensor::from_data(a.data(), {M, K}, DType::I128);
|
|
477
|
-
Tensor bg = Tensor::from_data(b.data(), {K, N}, DType::I128);
|
|
478
|
-
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
479
|
-
ms_b += time_once_ms([&] {
|
|
480
|
-
ag = Tensor::from_data(a.data(), {M, K}, DType::I128);
|
|
481
|
-
bg = Tensor::from_data(b.data(), {K, N}, DType::I128);
|
|
482
|
-
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
483
|
-
Tensor c = nn::matmul(ag, bg);
|
|
484
|
-
nn::sum(c).backward();
|
|
485
|
-
});
|
|
486
|
-
const std::vector<__int128> got_da = read_i128(ag.grad()), got_db = read_i128(bg.grad());
|
|
487
|
-
double err_da = mean_abs_error_i128(got_da, ref_da), err_db = mean_abs_error_i128(got_db, ref_db);
|
|
488
|
-
int ok_da = 0, ok_db = 0;
|
|
489
|
-
for (size_t i = 0; i < got_da.size(); ++i) if (got_da[i] == ref_da[i]) ++ok_da;
|
|
490
|
-
for (size_t i = 0; i < got_db.size(); ++i) if (got_db[i] == ref_db[i]) ++ok_db;
|
|
491
|
-
acc_b += 100.0 * (ok_da + ok_db) / (got_da.size() + got_db.size());
|
|
492
|
-
err_b += (err_da + err_db) / 2.0;
|
|
493
|
-
}
|
|
494
|
-
emit_metric("i128", 0, M, K, N, acc_f / DATA, err_f / DATA, ms_f / DATA, acc_b / DATA, err_b / DATA, ms_b / DATA);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
static void metric_mx() {
|
|
498
|
-
const int M = 256, K = 256, N = 256;
|
|
499
|
-
const int DATA = 4;
|
|
500
|
-
double acc_f = 0.0, err_f = 0.0, ms_f = 0.0, acc_b = 0.0, err_b = 0.0, ms_b = 0.0;
|
|
501
|
-
for (int d = 0; d < DATA; ++d) {
|
|
502
|
-
std::vector<float> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
503
|
-
fill_rand(a, 3000 + d, -2.0f, 2.0f);
|
|
504
|
-
fill_rand(b, 4000 + d, -2.0f, 2.0f);
|
|
505
|
-
std::vector<float> aq = mx_quantize(a, nullptr), bq = mx_quantize(b, nullptr);
|
|
506
|
-
const std::vector<float> ref_c = mx_quantize(ref_matmul_f32(aq, bq, M, K, N), nullptr);
|
|
507
|
-
std::vector<float> ref_da(static_cast<size_t>(M) * K), ref_db(static_cast<size_t>(K) * N);
|
|
508
|
-
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { float s = 0; for (int j = 0; j < N; ++j) s += bq[k * N + j]; ref_da[i * K + k] = s; }
|
|
509
|
-
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { float s = 0; for (int i = 0; i < M; ++i) s += aq[i * K + k]; ref_db[k * N + j] = s; }
|
|
510
|
-
ref_da = mx_quantize(ref_da, nullptr); ref_db = mx_quantize(ref_db, nullptr);
|
|
511
|
-
|
|
512
|
-
Tensor at = make_f32({M, K}, a).to(DType::MXFP4);
|
|
513
|
-
Tensor bt = make_f32({K, N}, b).to(DType::MXFP4);
|
|
514
|
-
const std::vector<float> got = f32_data(nn::matmul(at, bt).to(DType::F32));
|
|
515
|
-
double err = mean_abs_error_f32(got, ref_c);
|
|
516
|
-
int ok = 0; for (size_t i = 0; i < got.size(); ++i) if (std::fabs(got[i] - ref_c[i]) <= 0.75f + 0.1f * std::fabs(ref_c[i])) ++ok;
|
|
517
|
-
acc_f += 100.0 * ok / got.size(); err_f += err;
|
|
518
|
-
ms_f += time_once_ms([&] { Tensor c = nn::matmul(at, bt); (void)c; });
|
|
519
|
-
|
|
520
|
-
Tensor ag = make_f32({M, K}, a).to(DType::MXFP4), bg = make_f32({K, N}, b).to(DType::MXFP4);
|
|
521
|
-
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
522
|
-
ms_b += time_once_ms([&] {
|
|
523
|
-
ag = make_f32({M, K}, a).to(DType::MXFP4); bg = make_f32({K, N}, b).to(DType::MXFP4);
|
|
524
|
-
ag.set_requires_grad(true); bg.set_requires_grad(true);
|
|
525
|
-
Tensor c = nn::matmul(ag, bg);
|
|
526
|
-
nn::sum(c).backward();
|
|
527
|
-
});
|
|
528
|
-
const std::vector<float> got_da = f32_data(ag.grad().to(DType::F32)), got_db = f32_data(bg.grad().to(DType::F32));
|
|
529
|
-
double err_da = mean_abs_error_f32(got_da, ref_da), err_db = mean_abs_error_f32(got_db, ref_db);
|
|
530
|
-
int ok_da = 0, ok_db = 0;
|
|
531
|
-
for (size_t i = 0; i < got_da.size(); ++i) if (std::fabs(got_da[i] - ref_da[i]) <= 0.75f + 0.1f * std::fabs(ref_da[i])) ++ok_da;
|
|
532
|
-
for (size_t i = 0; i < got_db.size(); ++i) if (std::fabs(got_db[i] - ref_db[i]) <= 0.75f + 0.1f * std::fabs(ref_db[i])) ++ok_db;
|
|
533
|
-
acc_b += 100.0 * (ok_da + ok_db) / (got_da.size() + got_db.size());
|
|
534
|
-
err_b += (err_da + err_db) / 2.0;
|
|
535
|
-
}
|
|
536
|
-
emit_metric("mxfp4", 0, M, K, N, acc_f / DATA, err_f / DATA, ms_f / DATA, acc_b / DATA, err_b / DATA, ms_b / DATA);
|
|
537
|
-
|
|
538
|
-
const int STOCH_DATA = 2;
|
|
539
|
-
const int samples = 1024;
|
|
540
|
-
double s_acc_f = 0.0, s_err_f = 0.0, s_ms_f = 0.0, s_acc_b = 0.0, s_err_b = 0.0, s_ms_b = 0.0;
|
|
541
|
-
double s_ref_mean = 0.0, s_ref_std = 0.0, s_cand_mean = 0.0, s_cand_std = 0.0;
|
|
542
|
-
for (int d = 0; d < STOCH_DATA; ++d) {
|
|
543
|
-
std::vector<float> a(static_cast<size_t>(M) * K), b(static_cast<size_t>(K) * N);
|
|
544
|
-
fill_rand(a, 5000 + d, -2.0f, 2.0f);
|
|
545
|
-
fill_rand(b, 6000 + d, -2.0f, 2.0f);
|
|
546
|
-
const size_t out_n = static_cast<size_t>(M) * N;
|
|
547
|
-
std::vector<double> ref_sum(out_n, 0.0), ref_sq(out_n, 0.0), cand_sum(out_n, 0.0), cand_sq(out_n, 0.0);
|
|
548
|
-
std::vector<double> ref_da_sum(static_cast<size_t>(M) * K, 0.0), ref_da_sq(ref_da_sum.size(), 0.0);
|
|
549
|
-
std::vector<double> ref_db_sum(static_cast<size_t>(K) * N, 0.0), ref_db_sq(ref_db_sum.size(), 0.0);
|
|
550
|
-
std::vector<double> cand_da_sum(ref_da_sum.size(), 0.0), cand_da_sq(ref_da_sum.size(), 0.0);
|
|
551
|
-
std::vector<double> cand_db_sum(ref_db_sum.size(), 0.0), cand_db_sq(ref_db_sum.size(), 0.0);
|
|
552
|
-
std::mt19937_64 ref_rng(0xabcdefULL + d);
|
|
553
|
-
for (int t = 0; t < samples; ++t) {
|
|
554
|
-
const std::vector<float> raq = mx_quantize(a, &ref_rng), rbq = mx_quantize(b, &ref_rng);
|
|
555
|
-
const std::vector<float> rc = mx_quantize(ref_matmul_f32(raq, rbq, M, K, N), &ref_rng);
|
|
556
|
-
add_stats(ref_sum, ref_sq, rc);
|
|
557
|
-
std::vector<float> rda(static_cast<size_t>(M) * K), rdb(static_cast<size_t>(K) * N);
|
|
558
|
-
for (int i = 0; i < M; ++i) for (int k = 0; k < K; ++k) { float s = 0; for (int j = 0; j < N; ++j) s += rbq[k * N + j]; rda[i * K + k] = s; }
|
|
559
|
-
for (int k = 0; k < K; ++k) for (int j = 0; j < N; ++j) { float s = 0; for (int i = 0; i < M; ++i) s += raq[i * K + k]; rdb[k * N + j] = s; }
|
|
560
|
-
rda = mx_quantize(rda, nullptr); rdb = mx_quantize(rdb, nullptr);
|
|
561
|
-
add_stats(ref_da_sum, ref_da_sq, rda); add_stats(ref_db_sum, ref_db_sq, rdb);
|
|
562
|
-
|
|
563
|
-
const uint64_t seed = 100000 + static_cast<uint64_t>(d) * samples + t;
|
|
564
|
-
Tensor qa = make_f32({M, K}, a).to(DType::MXFP4, nn::Rounding::Stochastic, seed);
|
|
565
|
-
Tensor qb = make_f32({K, N}, b).to(DType::MXFP4, nn::Rounding::Stochastic, seed + 7919);
|
|
566
|
-
Tensor c = nn::matmul(qa, qb);
|
|
567
|
-
add_stats(cand_sum, cand_sq, f32_data(c.to(DType::F32)));
|
|
568
|
-
qa.set_requires_grad(true); qb.set_requires_grad(true);
|
|
569
|
-
Tensor cg = nn::matmul(qa, qb);
|
|
570
|
-
nn::sum(cg).backward();
|
|
571
|
-
add_stats(cand_da_sum, cand_da_sq, f32_data(qa.grad().to(DType::F32)));
|
|
572
|
-
add_stats(cand_db_sum, cand_db_sq, f32_data(qb.grad().to(DType::F32)));
|
|
573
|
-
}
|
|
574
|
-
StatScore f = score_stats(ref_sum, ref_sq, cand_sum, cand_sq, samples);
|
|
575
|
-
StatScore bscore = score_stats(ref_da_sum, ref_da_sq, cand_da_sum, cand_da_sq, samples);
|
|
576
|
-
StatScore bs2 = score_stats(ref_db_sum, ref_db_sq, cand_db_sum, cand_db_sq, samples);
|
|
577
|
-
s_acc_f += f.accuracy; s_err_f += f.mean_err;
|
|
578
|
-
s_acc_b += (bscore.accuracy + bs2.accuracy) / 2.0;
|
|
579
|
-
s_err_b += (bscore.mean_err + bs2.mean_err) / 2.0;
|
|
580
|
-
s_ref_mean += f.ref_mean_avg; s_ref_std += f.ref_std_avg;
|
|
581
|
-
s_cand_mean += f.cand_mean_avg; s_cand_std += f.cand_std_avg;
|
|
582
|
-
s_ms_f += time_once_ms([&] {
|
|
583
|
-
Tensor qa = make_f32({M, K}, a).to(DType::MXFP4, nn::Rounding::Stochastic, 7);
|
|
584
|
-
Tensor qb = make_f32({K, N}, b).to(DType::MXFP4, nn::Rounding::Stochastic, 11);
|
|
585
|
-
Tensor c = nn::matmul(qa, qb); (void)c;
|
|
586
|
-
}, 1);
|
|
587
|
-
s_ms_b += time_once_ms([&] {
|
|
588
|
-
Tensor qa = make_f32({M, K}, a).to(DType::MXFP4, nn::Rounding::Stochastic, 7);
|
|
589
|
-
Tensor qb = make_f32({K, N}, b).to(DType::MXFP4, nn::Rounding::Stochastic, 11);
|
|
590
|
-
qa.set_requires_grad(true); qb.set_requires_grad(true);
|
|
591
|
-
Tensor c = nn::matmul(qa, qb);
|
|
592
|
-
nn::sum(c).backward();
|
|
593
|
-
}, 1);
|
|
594
|
-
std::printf("STAT data=%d samples=%d fwd_acc=%.6f fwd_mean_err=%.9g fwd_std_ratio=%.9g bwd_acc=%.6f bwd_mean_err=%.9g bwd_std_ratio=%.9g ref_mean=%.9g ref_std=%.9g cand_mean=%.9g cand_std=%.9g\n",
|
|
595
|
-
d, samples, f.accuracy, f.mean_err, f.std_ratio, (bscore.accuracy + bs2.accuracy) / 2.0,
|
|
596
|
-
(bscore.mean_err + bs2.mean_err) / 2.0, (bscore.std_ratio + bs2.std_ratio) / 2.0,
|
|
597
|
-
f.ref_mean_avg, f.ref_std_avg, f.cand_mean_avg, f.cand_std_avg);
|
|
598
|
-
}
|
|
599
|
-
emit_metric("mxfp4", 1, M, K, N, s_acc_f / STOCH_DATA, s_err_f / STOCH_DATA, s_ms_f / STOCH_DATA,
|
|
600
|
-
s_acc_b / STOCH_DATA, s_err_b / STOCH_DATA, s_ms_b / STOCH_DATA);
|
|
601
|
-
std::printf("STAT dtype=mxfp4 stochastic=1 data=%d samples=%d ref_mean_avg=%.9g ref_std_avg=%.9g cand_mean_avg=%.9g cand_std_avg=%.9g\n",
|
|
602
|
-
STOCH_DATA, samples, s_ref_mean / STOCH_DATA, s_ref_std / STOCH_DATA,
|
|
603
|
-
s_cand_mean / STOCH_DATA, s_cand_std / STOCH_DATA);
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
int main() {
|
|
608
|
-
test_dtype_metadata();
|
|
609
|
-
test_casts_float();
|
|
610
|
-
test_casts_int();
|
|
611
|
-
test_integer_casts();
|
|
612
|
-
test_low_precision_casts();
|
|
613
|
-
test_views();
|
|
614
|
-
test_slices();
|
|
615
|
-
test_elementwise_broadcast();
|
|
616
|
-
test_reductions();
|
|
617
|
-
test_matmul_2d();
|
|
618
|
-
test_matmul_batch_and_nd();
|
|
619
|
-
test_autograd_add_mul();
|
|
620
|
-
test_autograd_matmul();
|
|
621
|
-
test_autograd_view_slice();
|
|
622
|
-
test_stochastic_stats();
|
|
623
|
-
test_threads();
|
|
624
|
-
test_all_dtype_alloc();
|
|
625
|
-
bench_matmul();
|
|
626
|
-
try { metric_f32(); } catch (const std::exception& e) { std::printf("METRIC dtype=f32 stochastic=0 error=%s\n", e.what()); }
|
|
627
|
-
try { metric_i128(); } catch (const std::exception& e) { std::printf("METRIC dtype=i128 stochastic=0 error=%s\n", e.what()); }
|
|
628
|
-
try { metric_mx(); } catch (const std::exception& e) { std::printf("METRIC dtype=mxfp4 stochastic=0 error=%s\n", e.what()); }
|
|
629
|
-
std::printf("SUMMARY %d %d\n", g_passed, g_failed);
|
|
630
|
-
return g_failed == 0 ? 0 : 1;
|
|
631
|
-
}
|