SPB Git

spb/wp40_uqo

Public MIT

WP40 RAID: paper sections (setup, micro/end-to-end/applications, threats, reproducibility, conclusion, appendices), E1–E3 reruns, parallel realized post-processing

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Nov 2, 2026) parent a9731b7 Browse files

32 changed files +1,943 −11

modified backends/metal/host/metal_backend.mm +3 −3
@@ -237,9 +237,9 @@ void regression_stats(std::span<const f64> x, std::span<const f64> y, std::span<
237 237 };
238 238
239 239 std::shared_ptr<Backend> make_metal_backend(const PrecisionPolicy& policy) {
240 − static std::mutex m; static std::weak_ptr<MetalBackend> cached; std::lock_guard<std::mutex> lk(m);
241 − if (auto p = cached.lock()) return p; // one device/queue/library per process (pipelines and buffers are reused)
242 − auto p = std::make_shared<MetalBackend>(policy); cached = p; if (!p->available()) return nullptr; return p;
240 + static std::mutex m; static std::shared_ptr<MetalBackend> cached; std::lock_guard<std::mutex> lk(m);
241 + if (cached) return cached->available() ? cached : nullptr; // one device/queue/library/pipeline cache/buffer pool per process
242 + cached = std::make_shared<MetalBackend>(policy); return cached->available() ? cached : nullptr;
243 243 }
244 244
245 245 /// Fused realized accumulators when the backend is Metal (falls back to the four generic calls otherwise).
modified benchmarks/end_to_end/bench_e3_garch.cpp +1 −1
@@ -44,7 +44,7 @@ int main(int argc, char** argv) {
44 44 ThreadPool::global().parallel_for(S, [&](usize a, usize b) { for (usize i = a; i < b; ++i) { auto& r = ret[syms[i]]; std::vector<f64> train(r.begin(), r.end() - static_cast<long>(test)); models::GarchFitOptions o; o.model = sp.m; o.dist = sp.d; o.forecast_horizon = 1; json row = {{"symbol", syms[i]}, {"model", sp.name}, {"n_train", train.size()}};
45 45 try { const f64 f0 = now(); auto e = models::garch_fit(train, o); row["seconds"] = now() - f0; row["converged"] = e.ok(); row["iterations"] = e.convergence.iterations; row["fevals"] = e.convergence.function_evaluations; row["loglik"] = -e.loss; row["coef"] = e.coefficients; row["se"] = e.inference ? e.inference->std_errors : std::vector<f64>{}; row["persistence"] = e.extra.value("persistence", 0.0); row["warnings"] = e.warnings;
46 46 // rolling 1-step forecasts over the test window WITHOUT refitting (parameters fixed at the training estimate; variance path updated with realized returns): QLIKE vs next-day RV
47 − if (e.ok()) { std::vector<f64> fc, act; for (usize k = 0; k < test; ++k) { std::vector<f64> hist(r.begin(), r.end() - static_cast<long>(test - k)); auto f = models::garch_forecast(e, hist, 1); fc.push_back(f[0]); act.push_back(rvd[syms[i]][r.size() - test + k]); } auto l = est::forecast_loss(act, fc); row["qlike_vs_rv"] = l.qlike; row["mse_vs_rv"] = l.mse; row["n_forecasts"] = l.n; std::vector<f64> naive; for (usize k = 0; k < test; ++k) naive.push_back(rvd[syms[i]][r.size() - test + k - 1]); auto ln = est::forecast_loss(act, naive); row["qlike_rw_rv"] = ln.qlike; } }
47 + if (e.ok()) { std::vector<f64> fc, act; for (usize k = 0; k < test; ++k) { std::vector<f64> hist(r.begin(), r.end() - static_cast<long>(test - k)); auto f = models::garch_forecast(e, hist, 1); fc.push_back(f[0]); act.push_back(rvd[syms[i]][rvd[syms[i]].size() - test + k]); } auto l = est::forecast_loss(act, fc); row["qlike_vs_rv"] = l.qlike; row["mse_vs_rv"] = l.mse; row["n_forecasts"] = l.n; std::vector<f64> naive; for (usize k = 0; k < test; ++k) naive.push_back(rvd[syms[i]][rvd[syms[i]].size() - test + k - 1]); auto ln = est::forecast_loss(act, naive); row["qlike_rw_rv"] = ln.qlike; } }
48 48 catch (const RaidError& ex) { row["error"] = ex.what(); row["converged"] = false; } rows[i] = row; } });
49 49 usize conv = 0; for (auto& r : rows) { conv += r.value("converged", false); r["kind"] = "fit"; r["experiment"] = "E3"; out << r.dump() << "\n"; }
50 50 out << json({{"kind", "fit_summary"}, {"experiment", "E3"}, {"model", sp.name}, {"S", S}, {"converged", conv}, {"wall_seconds_all", now() - t0}, {"threads", ThreadPool::global().size()}}).dump() << "\n"; out.flush();
added experiments/manifests/paper_assets.json +28 −0
@@ -0,0 +1,28 @@
1 +{
2 + "inputs": {
3 + "bench_primitives.jsonl": "f3de95928ef0d92f2fb1a89f81ed33118ff01f66ae3b2feb25f6e37d8ace292a",
4 + "e1_batched_rv.jsonl": "853960fae2a0aebe19ee97df2a255d044e105ce6911c7f5683fbdf871e0b7f12",
5 + "e2_har.jsonl": "b9ae608a015b33bea38aa9dfc8a282e9544f70a584d144e7160497c379da75a5",
6 + "e3_garch.jsonl": "679ac18132f6b16ce5618dfe15e9c5c6f416cf40d90f3515d893deb7a4131f91",
7 + "e4_connectedness.jsonl": "27f92310d6950ed7a60e5e9bfe1e361b7ac7f7a8636816475a2f02da8bad7673",
8 + "e5_inference.jsonl": "d4dcc2baa0a227334ac454d928a4ab8c27e209edbad6a4681f5d50a8a0ddff5b",
9 + "e6_pipeline.jsonl": "0816f1510693c4c028fe45b78482d7a8b009c6c9b4929f9a149d079401f935b0",
10 + "e6_baselines.jsonl": "cdbd901b0fa99cd2db9240b5fba13b9f00a852b40d010a9d64f4efcff218cdb8",
11 + "e7_summary.json": "1cbaa525a98b098eb26264d922033ee4d4f2df32049a6cf4b6fcb2a2f80a42cf"
12 + },
13 + "outputs": {
14 + "tables/tab_primitives.tex": "dfccbd67b68adc9c451a2f7f196a70de42cb612ecc9826285e2bc7fadb1db0ff",
15 + "figures/fig_primitives_throughput.pdf": "e9ce50655262712762064350c514e8dfd09fc2fce5c8db2027ed0e74b32b09eb",
16 + "tables/tab_e1.tex": "c5a0de42b79895abd2dc0cffba23b92f9a2048093579fa3529335e24c1a90a97",
17 + "figures/fig_e1.pdf": "53e26cdf3689df17adaebf18f1f95441f2bac33685ffe6e496efe223014a521d",
18 + "tables/tab_e2_accuracy.tex": "a337d1e20c1b1298f83e55984296b06ebfc41834c723e0270236e78022bb6f65",
19 + "tables/tab_e2_runtime.tex": "c43af1813c748886e5dc5c5f26257d3b14a4cc1dab5ea9cee5672e996f739abf",
20 + "tables/tab_e3_fits.tex": "d5d6adfb8f9644524e5deac5a37ce775df6cf32b7df9cbcad3ffb15a1a63587e",
21 + "tables/tab_e4.tex": "645ce562f6fce8f0a07495473237badb1190efe21f99e2dedb444f1b155208ef",
22 + "tables/tab_e5.tex": "69b53b60302201eed7a2ffba95827f88fa44b7ba8b3e642f820ee696652495d7",
23 + "tables/tab_e6.tex": "d06f84a429329af2a4f1e7831cff4cd4371a4189806fea8ba226e73890c47aee",
24 + "tables/tab_e7.tex": "26125ba7860235e8ec9bc7cbf9094525ae3badfa7684b0fdeceff0c444db27bb",
25 + "figures/fig_e7.pdf": "9e32e7a7c8d4fb0e1688ba282d05650b48cc53349a14aee834f4b19d5b306819"
26 + },
27 + "key_numbers_sha256": "4424672bebb9b3b34b9c9465c2afa92a10901aedfd967a1d7dc843855a0db242"
28 +}
\ No newline at end of file
added experiments/results/key_numbers.json +1230 −0
@@ -0,0 +1,1230 @@
1 +{
2 + "primitives": {
3 + "realized_fused@1x390": {
4 + "cpu1_ms": 0.0014998950064182281,
5 + "cpuMT_ms": 0.0014998950064182281,
6 + "metal_ms": 0.2344171516597271,
7 + "speedup": 0.006398401293585508,
8 + "verdict": "CPU"
9 + },
10 + "realized_fused@1x3900": {
11 + "cpu1_ms": 0.011624768376350403,
12 + "cpuMT_ms": 0.01116609200835228,
13 + "metal_ms": 0.6333747878670692,
14 + "speedup": 0.017629517660396336,
15 + "verdict": "CPU"
16 + },
17 + "realized_fused@10x390": {
18 + "cpu1_ms": 0.011292286217212677,
19 + "cpuMT_ms": 0.14200014993548393,
20 + "metal_ms": 0.2327919937670231,
21 + "speedup": 0.6099872578848089,
22 + "verdict": "CPU"
23 + },
24 + "realized_fused@1x39000": {
25 + "cpu1_ms": 0.18258299678564072,
26 + "cpuMT_ms": 0.1671668142080307,
27 + "metal_ms": 0.206624623388052,
28 + "speedup": 0.8090362681222294,
29 + "verdict": "CPU"
30 + },
31 + "realized_fused@10x3900": {
32 + "cpu1_ms": 0.18791621550917625,
33 + "cpuMT_ms": 0.135000329464674,
34 + "metal_ms": 0.16404176130890846,
35 + "speedup": 0.8229631795433707,
36 + "verdict": "CPU"
37 + },
38 + "realized_fused@100x390": {
39 + "cpu1_ms": 0.1871250569820404,
40 + "cpuMT_ms": 0.5520828999578953,
41 + "metal_ms": 0.22633420303463936,
42 + "speedup": 2.4392376077309077,
43 + "verdict": "Metal"
44 + },
45 + "realized_fused@1x390000": {
46 + "cpu1_ms": 2.032375428825617,
47 + "cpuMT_ms": 2.0858747884631157,
48 + "metal_ms": 0.9353337809443474,
49 + "speedup": 2.2300860195139536,
50 + "verdict": "Metal"
51 + },
52 + "realized_fused@10x39000": {
53 + "cpu1_ms": 2.572625409811735,
54 + "cpuMT_ms": 0.36349985748529434,
55 + "metal_ms": 0.7184999994933605,
56 + "speedup": 0.5059149029110798,
57 + "verdict": "tie"
58 + },
59 + "realized_fused@100x3900": {
60 + "cpu1_ms": 2.043417189270258,
61 + "cpuMT_ms": 0.6015831604599953,
62 + "metal_ms": 0.6413329392671585,
63 + "speedup": 0.9380200573315559,
64 + "verdict": "tie"
65 + },
66 + "realized_fused@1000x390": {
67 + "cpu1_ms": 2.235791180282831,
68 + "cpuMT_ms": 0.8399169892072678,
69 + "metal_ms": 0.33845799043774605,
70 + "speedup": 2.4815989367571367,
71 + "verdict": "Metal"
72 + },
73 + "realized_fused@10x390000": {
74 + "cpu1_ms": 20.89220890775323,
75 + "cpuMT_ms": 2.5267917662858963,
76 + "metal_ms": 1.0219174437224865,
77 + "speedup": 2.4725987229278337,
78 + "verdict": "Metal"
79 + },
80 + "realized_fused@100x39000": {
81 + "cpu1_ms": 20.590624772012234,
82 + "cpuMT_ms": 2.1904585883021355,
83 + "metal_ms": 1.1692089028656483,
84 + "speedup": 1.8734535658542084,
85 + "verdict": "Metal"
86 + },
87 + "realized_fused@1000x3900": {
88 + "cpu1_ms": 21.244540810585022,
89 + "cpuMT_ms": 1.7422502860426903,
90 + "metal_ms": 0.8750832639634609,
91 + "speedup": 1.9909537272506195,
92 + "verdict": "Metal"
93 + },
94 + "realized_fused@10000x390": {
95 + "cpu1_ms": 21.238334011286497,
96 + "cpuMT_ms": 2.125917002558708,
97 + "metal_ms": 2.2132499143481255,
98 + "speedup": 0.9605408719443508,
99 + "verdict": "tie"
100 + },
101 + "realized_fused@100x390000": {
102 + "cpu1_ms": 232.5868341140449,
103 + "cpuMT_ms": 18.79258267581463,
104 + "metal_ms": 8.720249868929386,
105 + "speedup": 2.1550509398559075,
106 + "verdict": "Metal"
107 + },
108 + "realized_fused@1000x39000": {
109 + "cpu1_ms": 238.77166723832488,
110 + "cpuMT_ms": 20.24729223921895,
111 + "metal_ms": 5.891874898225069,
112 + "speedup": 3.4364769430726474,
113 + "verdict": "Metal"
114 + },
115 + "realized_fused@10000x3900": {
116 + "cpu1_ms": 233.6724577471614,
117 + "cpuMT_ms": 15.69391693919897,
118 + "metal_ms": 7.8027499839663506,
119 + "speedup": 2.0113315140749037,
120 + "verdict": "Metal"
121 + },
122 + "regression_stats@1x390": {
123 + "cpu1_ms": 0.0031669624149799347,
124 + "cpuMT_ms": 0.0032088719308376312,
125 + "metal_ms": 0.894167460501194,
126 + "speedup": 0.003588669989219929,
127 + "verdict": "CPU"
128 + },
129 + "regression_stats@1x3900": {
130 + "cpu1_ms": 0.029958784580230713,
131 + "cpuMT_ms": 0.030207913368940353,
132 + "metal_ms": 0.3482499159872532,
133 + "speedup": 0.0867420550075482,
134 + "verdict": "CPU"
135 + },
136 + "regression_stats@10x390": {
137 + "cpu1_ms": 0.031250063329935074,
138 + "cpuMT_ms": 0.04133302718400955,
139 + "metal_ms": 0.6523327901959419,
140 + "speedup": 0.06336187265949686,
141 + "verdict": "CPU"
142 + },
143 + "regression_stats@1x39000": {
144 + "cpu1_ms": 0.30233291909098625,
145 + "cpuMT_ms": 0.3838753327727318,
146 + "metal_ms": 0.4085828550159931,
147 + "speedup": 0.9395287346496851,
148 + "verdict": "tie"
149 + },
150 + "regression_stats@10x3900": {
151 + "cpu1_ms": 0.2997498959302902,
152 + "cpuMT_ms": 0.07625017315149307,
153 + "metal_ms": 0.36174990236759186,
154 + "speedup": 0.2107814615911396,
155 + "verdict": "CPU"
156 + },
157 + "regression_stats@100x390": {
158 + "cpu1_ms": 0.36137504503130913,
159 + "cpuMT_ms": 0.17625000327825546,
160 + "metal_ms": 0.3363746218383312,
161 + "speedup": 0.5239693836444206,
162 + "verdict": "CPU"
163 + },
164 + "regression_stats@1x390000": {
165 + "cpu1_ms": 2.9733749106526375,
166 + "cpuMT_ms": 3.0428748577833176,
167 + "metal_ms": 0.7901252247393131,
168 + "speedup": 3.851129874745179,
169 + "verdict": "Metal"
170 + },
171 + "regression_stats@10x39000": {
172 + "cpu1_ms": 3.083667252212763,
173 + "cpuMT_ms": 0.5624173209071159,
174 + "metal_ms": 0.6961673498153687,
175 + "speedup": 0.8078766133692931,
176 + "verdict": "CPU"
177 + },
178 + "regression_stats@100x3900": {
179 + "cpu1_ms": 2.9982919804751873,
180 + "cpuMT_ms": 0.4399162717163563,
181 + "metal_ms": 0.5946666933596134,
182 + "speedup": 0.739769482011876,
183 + "verdict": "CPU"
184 + },
185 + "regression_stats@1000x390": {
186 + "cpu1_ms": 3.1211250461637974,
187 + "cpuMT_ms": 0.6971252150833607,
188 + "metal_ms": 0.5814996547996998,
189 + "speedup": 1.1988402904959397,
190 + "verdict": "tie"
191 + },
192 + "regression_stats@10x390000": {
193 + "cpu1_ms": 32.662583980709314,
194 + "cpuMT_ms": 6.654791999608278,
195 + "metal_ms": 4.117042291909456,
196 + "speedup": 1.6164011753500427,
197 + "verdict": "Metal"
198 + },
199 + "regression_stats@100x39000": {
200 + "cpu1_ms": 32.19050029292703,
201 + "cpuMT_ms": 3.1737093813717365,
202 + "metal_ms": 4.4694580137729645,
203 + "speedup": 0.7100881967325159,
204 + "verdict": "tie"
205 + },
206 + "regression_stats@1000x3900": {
207 + "cpu1_ms": 34.39616598188877,
208 + "cpuMT_ms": 3.421790897846222,
209 + "metal_ms": 3.796167206019163,
210 + "speedup": 0.9013804482638873,
211 + "verdict": "tie"
212 + },
213 + "regression_stats@10000x390": {
214 + "cpu1_ms": 30.644499696791172,
215 + "cpuMT_ms": 3.9592497050762177,
216 + "metal_ms": 4.190749954432249,
217 + "speedup": 0.944759231194123,
218 + "verdict": "tie"
219 + },
220 + "regression_stats@100x390000": {
221 + "cpu1_ms": 301.3692502863705,
222 + "cpuMT_ms": 33.760249614715576,
223 + "metal_ms": 30.70899983868003,
224 + "speedup": 1.0993601156685116,
225 + "verdict": "Metal"
226 + },
227 + "regression_stats@1000x39000": {
228 + "cpu1_ms": 324.0363751538098,
229 + "cpuMT_ms": 31.240916810929775,
230 + "metal_ms": 26.743208058178425,
231 + "speedup": 1.1681813469411308,
232 + "verdict": "Metal"
233 + },
234 + "regression_stats@10000x3900": {
235 + "cpu1_ms": 356.9141672924161,
236 + "cpuMT_ms": 37.49012481421232,
237 + "metal_ms": 26.574499905109406,
238 + "speedup": 1.4107556096287706,
239 + "verdict": "Metal"
240 + },
241 + "rolling_sumsq@1x390": {
242 + "cpu1_ms": 0.0009578652679920197,
243 + "cpuMT_ms": 0.0007920898497104645,
244 + "metal_ms": 0.2839169465005398,
245 + "speedup": 0.0027898646399008046,
246 + "verdict": "CPU"
247 + },
248 + "rolling_sumsq@1x3900": {
249 + "cpu1_ms": 0.0074999406933784485,
250 + "cpuMT_ms": 0.0074999406933784485,
251 + "metal_ms": 0.2416251227259636,
252 + "speedup": 0.031039573239594054,
253 + "verdict": "CPU"
254 + },
255 + "rolling_sumsq@10x390": {
256 + "cpu1_ms": 0.0071660615503787994,
257 + "cpuMT_ms": 0.01800013706088066,
258 + "metal_ms": 0.2032076008617878,
259 + "speedup": 0.08858003826895974,
260 + "verdict": "CPU"
261 + },
262 + "rolling_sumsq@1x39000": {
263 + "cpu1_ms": 0.0693327747285366,
264 + "cpuMT_ms": 0.07025012746453285,
265 + "metal_ms": 0.16458332538604736,
266 + "speedup": 0.42683623811679494,
267 + "verdict": "CPU"
268 + },
269 + "rolling_sumsq@10x3900": {
270 + "cpu1_ms": 0.06929086521267891,
271 + "cpuMT_ms": 0.04487484693527222,
272 + "metal_ms": 0.16070762649178505,
273 + "speedup": 0.2792328398774908,
274 + "verdict": "CPU"
275 + },
276 + "rolling_sumsq@100x390": {
277 + "cpu1_ms": 0.06991717964410782,
278 + "cpuMT_ms": 0.17983326688408852,
279 + "metal_ms": 0.2676667645573616,
280 + "speedup": 0.6718550477549103,
281 + "verdict": "tie"
282 + },
283 + "rolling_sumsq@1x390000": {
284 + "cpu1_ms": 0.6914162077009678,
285 + "cpuMT_ms": 0.718916766345501,
286 + "metal_ms": 0.7903752848505974,
287 + "speedup": 0.909589128259996,
288 + "verdict": "tie"
289 + },
290 + "rolling_sumsq@10x39000": {
291 + "cpu1_ms": 0.7095411419868469,
292 + "cpuMT_ms": 0.132707878947258,
293 + "metal_ms": 0.7357923313975334,
294 + "speedup": 0.18036050837224432,
295 + "verdict": "CPU"
296 + },
297 + "rolling_sumsq@100x3900": {
298 + "cpu1_ms": 0.806666910648346,
299 + "cpuMT_ms": 0.20312517881393433,
300 + "metal_ms": 0.6820829585194588,
301 + "speedup": 0.2978012810272249,
302 + "verdict": "CPU"
303 + },
304 + "rolling_sumsq@1000x390": {
305 + "cpu1_ms": 0.7188748568296432,
306 + "cpuMT_ms": 0.2710837870836258,
307 + "metal_ms": 0.9075421839952469,
308 + "speedup": 0.29870103215504695,
309 + "verdict": "CPU"
310 + },
311 + "rolling_sumsq@10x390000": {
312 + "cpu1_ms": 6.913874763995409,
313 + "cpuMT_ms": 1.7658751457929611,
314 + "metal_ms": 2.544207964092493,
315 + "speedup": 0.6940765734230536,
316 + "verdict": "CPU"
317 + },
318 + "rolling_sumsq@100x39000": {
319 + "cpu1_ms": 7.338124793022871,
320 + "cpuMT_ms": 1.0874588042497635,
321 + "metal_ms": 2.226833254098892,
322 + "speedup": 0.4883431672524638,
323 + "verdict": "CPU"
324 + },
325 + "rolling_sumsq@1000x3900": {
326 + "cpu1_ms": 6.95441709831357,
327 + "cpuMT_ms": 1.0273326188325882,
328 + "metal_ms": 2.144791651517153,
329 + "speedup": 0.47898947112456725,
330 + "verdict": "CPU"
331 + },
332 + "rolling_sumsq@10000x390": {
333 + "cpu1_ms": 7.047916762530804,
334 + "cpuMT_ms": 1.07216602191329,
335 + "metal_ms": 2.1627498790621758,
336 + "speedup": 0.49574203299838304,
337 + "verdict": "CPU"
338 + },
339 + "rolling_sumsq@100x390000": {
340 + "cpu1_ms": 69.62170917540789,
341 + "cpuMT_ms": 9.413291700184345,
342 + "metal_ms": 14.852333813905716,
343 + "speedup": 0.6337920907333103,
344 + "verdict": "CPU"
345 + },
346 + "rolling_sumsq@1000x39000": {
347 + "cpu1_ms": 70.26320835575461,
348 + "cpuMT_ms": 8.31229193136096,
349 + "metal_ms": 14.728832989931107,
350 + "speedup": 0.5643550943271196,
351 + "verdict": "CPU"
352 + },
353 + "rolling_sumsq@10000x3900": {
354 + "cpu1_ms": 69.22604190185666,
355 + "cpuMT_ms": 6.54304213821888,
356 + "metal_ms": 14.753291849046946,
357 + "speedup": 0.4434970991671636,
358 + "verdict": "CPU"
359 + },
360 + "garch_nll_P1@1x390": {
361 + "cpu1_ms": 0.0017909333109855652,
362 + "cpuMT_ms": 0.0017499551177024841,
363 + "metal_ms": 0.9180000051856041,
364 + "speedup": 0.0019062691806288963,
365 + "verdict": "CPU"
366 + },
367 + "garch_nll_P1@1x3900": {
368 + "cpu1_ms": 0.016250181943178177,
369 + "cpuMT_ms": 0.01695798709988594,
370 + "metal_ms": 1.348957885056734,
371 + "speedup": 0.012571176081729732,
372 + "verdict": "CPU"
373 + },
374 + "garch_nll_P1@10x390": {
375 + "cpu1_ms": 0.021916814148426056,
376 + "cpuMT_ms": 0.02929195761680603,
377 + "metal_ms": 0.3432091325521469,
378 + "speedup": 0.08534725576498299,
379 + "verdict": "CPU"
380 + },
381 + "garch_nll_P1@10x3900": {
382 + "cpu1_ms": 0.2155420370399952,
383 + "cpuMT_ms": 0.06916606798768044,
384 + "metal_ms": 1.4300826005637646,
385 + "speedup": 0.04836508601699924,
386 + "verdict": "CPU"
387 + },
388 + "garch_nll_P1@100x390": {
389 + "cpu1_ms": 0.1916671171784401,
390 + "cpuMT_ms": 0.16116676852107048,
391 + "metal_ms": 0.6238752976059914,
392 + "speedup": 0.2583317036906555,
393 + "verdict": "CPU"
394 + },
395 + "garch_nll_P1@100x3900": {
396 + "cpu1_ms": 1.6154590994119644,
397 + "cpuMT_ms": 0.20695803686976433,
398 + "metal_ms": 1.6493331640958786,
399 + "speedup": 0.12547982504384633,
400 + "verdict": "CPU"
401 + },
402 + "garch_nll_P1@1000x390": {
403 + "cpu1_ms": 1.6390001401305199,
404 + "cpuMT_ms": 0.2765827812254429,
405 + "metal_ms": 1.1531668715178967,
406 + "speedup": 0.23984627728802252,
407 + "verdict": "CPU"
408 + },
409 + "garch_nll_P1@1000x3900": {
410 + "cpu1_ms": 18.310166895389557,
411 + "cpuMT_ms": 1.4978330582380295,
412 + "metal_ms": 7.2068748995661736,
413 + "speedup": 0.20783391957146272,
414 + "verdict": "CPU"
415 + },
416 + "garch_nll_P1@10000x390": {
417 + "cpu1_ms": 17.741417046636343,
418 + "cpuMT_ms": 2.2433330304920673,
419 + "metal_ms": 6.75466563552618,
420 + "speedup": 0.33211607376881125,
421 + "verdict": "CPU"
422 + },
423 + "garch_nll_P1@10000x3900": {
424 + "cpu1_ms": 162.26391727104783,
425 + "cpuMT_ms": 13.83341709151864,
426 + "metal_ms": 61.06641702353954,
427 + "speedup": 0.22653068193252948,
428 + "verdict": "CPU"
429 + },
430 + "garch_nll_P64@1x390": {
431 + "cpu1_ms": 0.08287513628602028,
432 + "cpuMT_ms": 0.17224997282028198,
433 + "metal_ms": 0.5012080073356628,
434 + "speedup": 0.3436696347608925,
435 + "verdict": "CPU"
436 + },
437 + "garch_nll_P64@1x3900": {
438 + "cpu1_ms": 0.8078329265117645,
439 + "cpuMT_ms": 0.14187488704919815,
440 + "metal_ms": 1.4235423877835274,
441 + "speedup": 0.09966326838366861,
442 + "verdict": "CPU"
443 + },
444 + "garch_nll_P64@10x390": {
445 + "cpu1_ms": 0.8257082663476467,
446 + "cpuMT_ms": 0.2438751980662346,
447 + "metal_ms": 1.0179998353123665,
448 + "speedup": 0.23956310168891443,
449 + "verdict": "CPU"
450 + },
451 + "garch_nll_P64@10x3900": {
452 + "cpu1_ms": 8.083874825388193,
453 + "cpuMT_ms": 0.775500200688839,
454 + "metal_ms": 1.3822498731315136,
455 + "speedup": 0.5610419763916696,
456 + "verdict": "CPU"
457 + },
458 + "garch_nll_P64@100x390": {
459 + "cpu1_ms": 8.346542250365019,
460 + "cpuMT_ms": 1.005750149488449,
461 + "metal_ms": 0.5332920700311661,
462 + "speedup": 1.8859274420294159,
463 + "verdict": "Metal"
464 + },
465 + "garch_nll_P64@100x3900": {
466 + "cpu1_ms": 80.1338329911232,
467 + "cpuMT_ms": 6.173874717205763,
468 + "metal_ms": 2.1704169921576977,
469 + "speedup": 2.84455693975565,
470 + "verdict": "Metal"
471 + },
472 + "garch_nll_P64@1000x390": {
473 + "cpu1_ms": 96.79854195564985,
474 + "cpuMT_ms": 8.48708301782608,
475 + "metal_ms": 2.336665987968445,
476 + "speedup": 3.632133587567199,
477 + "verdict": "Metal"
478 + },
479 + "garch_nll_P64@1000x3900": {
480 + "cpu1_ms": 856.1791670508683,
481 + "cpuMT_ms": 81.50566695258021,
482 + "metal_ms": 10.272707790136337,
483 + "speedup": 7.934195016316967,
484 + "verdict": "Metal"
485 + }
486 + },
487 + "breakeven": {
488 + "realized_fused": {
489 + "smallest_metal_win": 39000,
490 + "largest_cpu_win": 39000,
491 + "max_speedup": 3.4364769430726474,
492 + "min_speedup": 0.006398401293585508
493 + },
494 + "regression_stats": {
495 + "smallest_metal_win": 390000,
496 + "largest_cpu_win": 390000,
497 + "max_speedup": 3.851129874745179,
498 + "min_speedup": 0.003588669989219929
499 + },
500 + "rolling_sumsq": {
501 + "smallest_metal_win": null,
502 + "largest_cpu_win": 39000000,
503 + "max_speedup": 0.909589128259996,
504 + "min_speedup": 0.0027898646399008046
505 + },
506 + "garch_nll_P1": {
507 + "smallest_metal_win": null,
508 + "largest_cpu_win": 39000000,
509 + "max_speedup": 0.33211607376881125,
510 + "min_speedup": 0.0019062691806288963
511 + },
512 + "garch_nll_P64": {
513 + "smallest_metal_win": 39000,
514 + "largest_cpu_win": 39000,
515 + "max_speedup": 7.934195016316967,
516 + "min_speedup": 0.09966326838366861
517 + }
518 + },
519 + "E1": {
520 + "real_S1_day": {
521 + "elements": 88350,
522 + "cpu1_ms": 0.7735420949757099,
523 + "cpuMT_ms": 0.9354581125080585,
524 + "metal_ms": 0.9417501278221607,
525 + "metal_unfused_ms": 2.271167002618313,
526 + "speedup_MT": 0.993318805988747,
527 + "fusion_gain": 2.4116450165719523,
528 + "max_rel_err": 3.216772293576152e-08,
529 + "metal_wins": false,
530 + "cpu_wins": false
531 + },
532 + "real_S1_week": {
533 + "elements": 87732,
534 + "cpu1_ms": 0.8084997534751892,
535 + "cpuMT_ms": 0.9053335525095463,
536 + "metal_ms": 0.7747076451778412,
537 + "metal_unfused_ms": 1.9873343408107758,
538 + "speedup_MT": 1.1686131641333148,
539 + "fusion_gain": 2.5652700772748473,
540 + "max_rel_err": 1.5355137638729577e-08,
541 + "metal_wins": true,
542 + "cpu_wins": false
543 + },
544 + "real_S1_month": {
545 + "elements": 85202,
546 + "cpu1_ms": 0.5944999866187572,
547 + "cpuMT_ms": 0.263875350356102,
548 + "metal_ms": 0.32645929604768753,
549 + "metal_unfused_ms": 1.0339580476284027,
550 + "speedup_MT": 0.8082947967809022,
551 + "fusion_gain": 3.167188253317091,
552 + "max_rel_err": 5.502644725750323e-09,
553 + "metal_wins": false,
554 + "cpu_wins": true
555 + },
556 + "real_S1_year": {
557 + "elements": 88350,
558 + "cpu1_ms": 0.8845417760312557,
559 + "cpuMT_ms": 0.7403329946100712,
560 + "metal_ms": 0.5079996772110462,
561 + "metal_unfused_ms": 1.289083156734705,
562 + "speedup_MT": 1.4573493406030318,
563 + "fusion_gain": 2.537566881561543,
564 + "max_rel_err": 1.1553520565395228e-09,
565 + "metal_wins": true,
566 + "cpu_wins": false
567 + },
568 + "real_S10_day": {
569 + "elements": 660818,
570 + "cpu1_ms": 4.591624718159437,
571 + "cpuMT_ms": 1.333874650299549,
572 + "metal_ms": 1.396208070218563,
573 + "metal_unfused_ms": 1.9492078572511673,
574 + "speedup_MT": 0.9553552072584308,
575 + "fusion_gain": 1.3960726189944148,
576 + "max_rel_err": 1.1707127776091667e-07,
577 + "metal_wins": false,
578 + "cpu_wins": false
579 + },
580 + "real_S10_week": {
581 + "elements": 655478,
582 + "cpu1_ms": 4.3206666596233845,
583 + "cpuMT_ms": 1.0201670229434967,
584 + "metal_ms": 0.8149999193847179,
585 + "metal_unfused_ms": 1.9696662202477455,
586 + "speedup_MT": 1.2517388022733416,
587 + "fusion_gain": 2.416768607455495,
588 + "max_rel_err": 4.3164647273400464e-08,
589 + "metal_wins": false,
590 + "cpu_wins": false
591 + },
592 + "real_S10_month": {
593 + "elements": 634608,
594 + "cpu1_ms": 4.162374883890152,
595 + "cpuMT_ms": 0.9038751013576984,
596 + "metal_ms": 1.0571670718491077,
597 + "metal_unfused_ms": 1.4940421096980572,
598 + "speedup_MT": 0.8549974033685291,
599 + "fusion_gain": 1.413250705098868,
600 + "max_rel_err": 1.5374929954074983e-08,
601 + "metal_wins": false,
602 + "cpu_wins": false
603 + },
604 + "real_S10_year": {
605 + "elements": 660818,
606 + "cpu1_ms": 4.490583203732967,
607 + "cpuMT_ms": 1.3055838644504547,
608 + "metal_ms": 1.4134589582681656,
609 + "metal_unfused_ms": 2.377707976847887,
610 + "speedup_MT": 0.9236800664167254,
611 + "fusion_gain": 1.6821910271531078,
612 + "max_rel_err": 3.180737515032068e-09,
613 + "metal_wins": false,
614 + "cpu_wins": false
615 + },
616 + "real_S100_day": {
617 + "elements": 4857139,
618 + "cpu1_ms": 29.412207659333944,
619 + "cpuMT_ms": 3.8021672517061234,
620 + "metal_ms": 4.112166818231344,
621 + "metal_unfused_ms": 7.726917043328285,
622 + "speedup_MT": 0.9246140586634681,
623 + "fusion_gain": 1.8790378369551788,
624 + "max_rel_err": 1.463952514147405e-07,
625 + "metal_wins": false,
626 + "cpu_wins": false
627 + },
628 + "real_S100_week": {
629 + "elements": 4814500,
630 + "cpu1_ms": 28.37820863351226,
631 + "cpuMT_ms": 3.745041787624359,
632 + "metal_ms": 3.630833700299263,
633 + "metal_unfused_ms": 6.0623749159276485,
634 + "speedup_MT": 1.031455058741931,
635 + "fusion_gain": 1.6696922570229453,
636 + "max_rel_err": 1.3949921298073233e-07,
637 + "metal_wins": false,
638 + "cpu_wins": false
639 + },
640 + "real_S100_month": {
641 + "elements": 4656568,
642 + "cpu1_ms": 27.86025032401085,
643 + "cpuMT_ms": 3.613583743572235,
644 + "metal_ms": 3.4282919950783253,
645 + "metal_unfused_ms": 5.321166943758726,
646 + "speedup_MT": 1.054047831619919,
647 + "fusion_gain": 1.552133526373431,
648 + "max_rel_err": 6.515494931810648e-08,
649 + "metal_wins": true,
650 + "cpu_wins": false
651 + },
652 + "real_S100_year": {
653 + "elements": 4817403,
654 + "cpu1_ms": 29.63858423754573,
655 + "cpuMT_ms": 3.890958148986101,
656 + "metal_ms": 3.2545411959290504,
657 + "metal_unfused_ms": 5.527874920517206,
658 + "speedup_MT": 1.1955473643575671,
659 + "fusion_gain": 1.6985112763150025,
660 + "max_rel_err": 1.220912079679724e-08,
661 + "metal_wins": true,
662 + "cpu_wins": false
663 + },
664 + "real_S926_day": {
665 + "elements": 40408948,
666 + "cpu1_ms": 240.89466594159603,
667 + "cpuMT_ms": 29.765665996819735,
668 + "metal_ms": 27.769084088504314,
669 + "metal_unfused_ms": 51.85075011104345,
670 + "speedup_MT": 1.0718994512729338,
671 + "fusion_gain": 1.8672113904004608,
672 + "max_rel_err": 1.6198392060671777e-07,
673 + "metal_wins": false,
674 + "cpu_wins": false
675 + },
676 + "real_S926_week": {
677 + "elements": 40062893,
678 + "cpu1_ms": 235.06820807233453,
679 + "cpuMT_ms": 29.190624598413706,
680 + "metal_ms": 24.931750260293484,
681 + "metal_unfused_ms": 44.04070833697915,
682 + "speedup_MT": 1.1708213139332997,
683 + "fusion_gain": 1.7664507255681425,
684 + "max_rel_err": 1.3949921298073233e-07,
685 + "metal_wins": true,
686 + "cpu_wins": false
687 + },
688 + "real_S926_month": {
689 + "elements": 38769255,
690 + "cpu1_ms": 231.19533294811845,
691 + "cpuMT_ms": 28.66779128089547,
692 + "metal_ms": 20.429750438779593,
693 + "metal_unfused_ms": 38.208582904189825,
694 + "speedup_MT": 1.4032374681620434,
695 + "fusion_gain": 1.8702422733301036,
696 + "max_rel_err": 6.515494931810648e-08,
697 + "metal_wins": true,
698 + "cpu_wins": false
699 + },
700 + "real_S926_year": {
701 + "elements": 39917613,
702 + "cpu1_ms": 241.63200007751584,
703 + "cpuMT_ms": 28.705624863505363,
704 + "metal_ms": 20.413792226463556,
705 + "metal_unfused_ms": 39.6507503464818,
706 + "speedup_MT": 1.406187764872645,
707 + "fusion_gain": 1.9423510294711575,
708 + "max_rel_err": 1.4314531656643865e-08,
709 + "metal_wins": true,
710 + "cpu_wins": false
711 + },
712 + "synthetic_S10000_day": {
713 + "elements": 3900000,
714 + "cpu1_ms": 21.742417011409998,
715 + "cpuMT_ms": 2.6805000379681587,
716 + "metal_ms": 3.3537917770445347,
717 + "metal_unfused_ms": null,
718 + "speedup_MT": 0.7992446210629983,
719 + "fusion_gain": null,
720 + "max_rel_err": 4.9499305589440414e-08,
721 + "metal_wins": false,
722 + "cpu_wins": true
723 + },
724 + "synthetic_S10000_week": {
725 + "elements": 19500000,
726 + "cpu1_ms": 106.63599986582994,
727 + "cpuMT_ms": 12.074083089828491,
728 + "metal_ms": 9.116541128605604,
729 + "metal_unfused_ms": null,
730 + "speedup_MT": 1.3244149200339592,
731 + "fusion_gain": null,
732 + "max_rel_err": 3.356929504238224e-08,
733 + "metal_wins": true,
734 + "cpu_wins": false
735 + },
736 + "synthetic_S10000_month": {
737 + "elements": 85800000,
738 + "cpu1_ms": 483.16720919683576,
739 + "cpuMT_ms": 54.07591676339507,
740 + "metal_ms": 35.40699975565076,
741 + "metal_unfused_ms": null,
742 + "speedup_MT": 1.5272662788878308,
743 + "fusion_gain": null,
744 + "max_rel_err": 2.7721528772327113e-08,
745 + "metal_wins": true,
746 + "cpu_wins": false
747 + }
748 + },
749 + "E2": {
750 + "accuracy": {
751 + "h1": {
752 + "n": 100,
753 + "har": 0.19596646955954006,
754 + "loghar": 0.20549043426692812,
755 + "harq": 0.20287854864925106,
756 + "rw": 0.2509836820568328,
757 + "har_beats_rw_pct": 84.0,
758 + "fits_per_symbol": 132.0
759 + },
760 + "h5": {
761 + "n": 100,
762 + "har": 0.14599330475845337,
763 + "loghar": 0.13780663128811915,
764 + "harq": 0.15032513333481387,
765 + "rw": 0.2392329633290453,
766 + "har_beats_rw_pct": 86.0,
767 + "fits_per_symbol": 128.0
768 + },
769 + "h22": {
770 + "n": 100,
771 + "har": 0.13380122970874658,
772 + "loghar": 0.11202433356845258,
773 + "harq": 0.1317067007400809,
774 + "rw": 0.30092923731362164,
775 + "har_beats_rw_pct": 78.0,
776 + "fits_per_symbol": 111.0
777 + }
778 + },
779 + "runtime": {
780 + "10": {
781 + "per_series_cpu1": 0.07679173722863197,
782 + "per_series_cpuMT": 0.053416937589645386,
783 + "batched_cpu": 0.10233419016003609,
784 + "batched_metal": 0.3199586644768715,
785 + "T": 252
786 + },
787 + "100": {
788 + "per_series_cpu1": 0.7653338834643364,
789 + "per_series_cpuMT": 0.14466699212789536,
790 + "batched_cpu": 0.6509590893983841,
791 + "batched_metal": 0.7528341375291348,
792 + "T": 252
793 + },
794 + "781": {
795 + "per_series_cpu1": 6.033665966242552,
796 + "per_series_cpuMT": 0.6839591078460217,
797 + "batched_cpu": 3.8614580407738686,
798 + "batched_metal": 4.703125450760126,
799 + "T": 251
800 + }
801 + }
802 + },
803 + "E3": {
804 + "symbols": 888,
805 + "daily_history": 845,
806 + "garch.n": {
807 + "n": 888,
808 + "converged_pct": 100.0,
809 + "median_iter": 14.0,
810 + "median_ms": 2.8645414859056473,
811 + "median_persistence": 0.962240963021934,
812 + "qlike": 0.4032196350815048,
813 + "qlike_rw": 0.27550123596742626,
814 + "n_train": 2458.5,
815 + "n_eval": 888
816 + },
817 + "gjr.n": {
818 + "n": 888,
819 + "converged_pct": 98.42342342342343,
820 + "median_iter": 18.0,
821 + "median_ms": 3.9954171516001225,
822 + "median_persistence": 0.9710634836054904,
823 + "qlike": 0.39931764172261175,
824 + "qlike_rw": 0.2734243088287934,
825 + "n_train": 2458.5,
826 + "n_eval": 874
827 + },
828 + "egarch.n": {
829 + "n": 888,
830 + "converged_pct": 92.7927927927928,
831 + "median_iter": 17.0,
832 + "median_ms": 18.152124946936965,
833 + "median_persistence": 0.9561998303082433,
834 + "qlike": 0.39635306701502293,
835 + "qlike_rw": 0.27241123059255185,
836 + "n_train": 2458.5,
837 + "n_eval": 824
838 + },
839 + "garch.t": {
840 + "n": 888,
841 + "converged_pct": 100.0,
842 + "median_iter": 18.0,
843 + "median_ms": 6.74610398709774,
844 + "median_persistence": 0.9727760170446753,
845 + "qlike": 0.3908846216118549,
846 + "qlike_rw": 0.27550123596742626,
847 + "n_train": 2458.5,
848 + "n_eval": 888
849 + },
850 + "grid": {
851 + "S": 888,
852 + "P": 256,
853 + "cpuMT_ms": 117.02079232782125,
854 + "metal_ms": 22.934832610189915,
855 + "max_rel_err_nll": 0.001696265571243037,
856 + "argmin_agreement": 888,
857 + "argmin_total": 888
858 + }
859 + },
860 + "E4": {
861 + "10": {
862 + "days_ok": 182,
863 + "days_skipped": 70,
864 + "cond_median": 80.51310121584409,
865 + "cond_max": 1114.4148164242238,
866 + "lw": 0.15825066990879552,
867 + "dy_windows": 133,
868 + "dy_total": 37.15801851010236,
869 + "dy_ms": 0.5304999649524689,
870 + "dy_failures": 0
871 + },
872 + "30": {
873 + "days_ok": 129,
874 + "days_skipped": 123,
875 + "cond_median": 421.7546397917854,
876 + "cond_max": 1982.0116043100866,
877 + "lw": 0.26298332837244776,
878 + "dy_windows": 133,
879 + "dy_total": 69.67433187119195,
880 + "dy_ms": 2.2807088680565357,
881 + "dy_failures": 0
882 + },
883 + "60": {
884 + "days_ok": 95,
885 + "days_skipped": 157,
886 + "cond_median": 5918.2160036330415,
887 + "cond_max": 4.004356648938842e+297,
888 + "lw": 0.3264154734521777,
889 + "dy_windows": 133,
890 + "dy_total": 87.50466794156553,
891 + "dy_ms": 8.867499884217978,
892 + "dy_failures": 0
893 + },
894 + "100": {
895 + "days_ok": 88,
896 + "days_skipped": 164,
897 + "cond_median": 1.3073204915206876e+298,
898 + "cond_max": 4.628848885035562e+298,
899 + "lw": 0.3323406895220246,
900 + "dy_windows": 133,
901 + "dy_total": 97.24027926801519,
902 + "dy_ms": 28.755417093634605,
903 + "dy_failures": 0
904 + }
905 + },
906 + "E5": {
907 + "garch_n500": {
908 + "mu": {
909 + "bias": -0.00048301580401779385,
910 + "coverage95": 0.95,
911 + "rmse": 0.03830937699585465
912 + },
913 + "omega": {
914 + "bias": 0.020140386483790382,
915 + "coverage95": 0.954,
916 + "rmse": 0.04874063710909834
917 + },
918 + "alpha": {
919 + "bias": 0.0021013443234158386,
920 + "coverage95": 0.896,
921 + "rmse": 0.030365422987920495
922 + },
923 + "beta": {
924 + "bias": -0.025611816484074457,
925 + "coverage95": 0.916,
926 + "rmse": 0.07085785700063447
927 + },
928 + "converged": 1000,
929 + "R": 1000
930 + },
931 + "garch_n2000": {
932 + "mu": {
933 + "bias": 0.0001115840803594372,
934 + "coverage95": 0.961,
935 + "rmse": 0.018994072598395778
936 + },
937 + "omega": {
938 + "bias": 0.0034273370897326973,
939 + "coverage95": 0.972,
940 + "rmse": 0.009288147787445019
941 + },
942 + "alpha": {
943 + "bias": 0.0007353540065208454,
944 + "coverage95": 0.932,
945 + "rmse": 0.013671869751518313
946 + },
947 + "beta": {
948 + "bias": -0.004814929382042228,
949 + "coverage95": 0.936,
950 + "rmse": 0.019568746480840227
951 + },
952 + "converged": 1000,
953 + "R": 1000
954 + },
955 + "har_h1": [
956 + 0.945,
957 + 0.939,
958 + 0.946,
959 + 0.941
960 + ],
961 + "har_h5": [
962 + 0.909,
963 + 0.936,
964 + 0.931,
965 + 0.9
966 + ],
967 + "repro_bootstrap": {
968 + "bitwise_identical_across_threads": true,
969 + "replicas": 2000,
970 + "threads": [
971 + 1,
972 + 4,
973 + 18
974 + ]
975 + },
976 + "repro_realized": {
977 + "cpu_threads_vs_1_identical": true,
978 + "metal_backend_used": "metal",
979 + "metal_runs_identical": true,
980 + "metal_vs_cpu_max_rel_rv": 3.6599268443269906e-08
981 + }
982 + },
983 + "E6": {
984 + "bars_per_file": 2367760.5,
985 + "read_s": 0.06473202048800886,
986 + "prep_s": 0.02098981267772615,
987 + "est_cpu_s": 0.03066229191608727,
988 + "est_metal_s": 0.03653329168446362,
989 + "RAID cpu": {
990 + "median_s": 0.1182449993211776,
991 + "ci": [
992 + 0.09712429158389568,
993 + 0.12820672919042408
994 + ],
995 + "bars_per_s": 20024191.412684422
996 + },
997 + "RAID metal": {
998 + "median_s": 0.12477712496183813,
999 + "ci": [
1000 + 0.10097172926180065,
1001 + 0.134304832899943
1002 + ],
1003 + "bars_per_s": 18975918.067707974
1004 + },
1005 + "polars": {
1006 + "median_s": 0.16476131248055026,
1007 + "ci": [
1008 + 0.14585839601932094,
1009 + 0.17225766699993983
1010 + ],
1011 + "bars_per_s": 14370852.38247
1012 + },
1013 + "duckdb": {
1014 + "median_s": 0.1637031040736474,
1015 + "ci": [
1016 + 0.15818560402840376,
1017 + 0.16537331248400733
1018 + ],
1019 + "bars_per_s": 14463748.341233544
1020 + },
1021 + "pandas": {
1022 + "median_s": 2.5584507705061696,
1023 + "ci": [
1024 + 2.355445542023517,
1025 + 2.6337175624794327
1026 + ],
1027 + "bars_per_s": 925466.5078161957
1028 + }
1029 + },
1030 + "E7": {
1031 + "m2m8a": {
1032 + "chip": "Apple M2",
1033 + "gpu_cores": 10,
1034 + "cpu_threads": "8",
1035 + "mem_gb": 8,
1036 + "macos": "26.5.1",
1037 + "cold_compile_s": 0.109846416,
1038 + "warm_compile_s": 0.000537584,
1039 + "realized_fused@1000x3900_speedup_MT": 3.990399191000979,
1040 + "regression_stats@1000x3900_speedup_MT": 1.6134322509601442,
1041 + "garch_nll_P64@1000x390_speedup_MT": 6.670422238065105,
1042 + "rolling_sumsq@1000x3900_speedup_MT": 0.6518314749487951,
1043 + "realized_fused@1000x3900_cpuMT_ms": 5.524458014406264,
1044 + "realized_fused@1000x3900_metal_ms": 1.3844374334439635,
1045 + "tests": "pass / pass"
1046 + },
1047 + "M2M32c": {
1048 + "chip": "Apple M2 Max",
1049 + "gpu_cores": 30,
1050 + "cpu_threads": "12",
1051 + "mem_gb": 32,
1052 + "macos": "26.5.1",
1053 + "cold_compile_s": 0.048325125,
1054 + "warm_compile_s": 0.000524916,
1055 + "realized_fused@1000x3900_speedup_MT": 3.6053646941003636,
1056 + "regression_stats@1000x3900_speedup_MT": 1.35476806903387,
1057 + "garch_nll_P64@1000x390_speedup_MT": 7.836957668549106,
1058 + "rolling_sumsq@1000x3900_speedup_MT": 0.5173055981132895,
1059 + "realized_fused@1000x3900_cpuMT_ms": 3.611000021919608,
1060 + "realized_fused@1000x3900_metal_ms": 1.0015630396082997,
1061 + "tests": "pass / pass"
1062 + },
1063 + "M2U64": {
1064 + "chip": "Apple M2 Ultra",
1065 + "gpu_cores": 60,
1066 + "cpu_threads": "24",
1067 + "mem_gb": 64,
1068 + "macos": "26.5",
1069 + "cold_compile_s": 0.049152792,
1070 + "warm_compile_s": 0.000613,
1071 + "realized_fused@1000x3900_speedup_MT": 2.1845461259882226,
1072 + "regression_stats@1000x3900_speedup_MT": 1.0830287027429175,
1073 + "garch_nll_P64@1000x390_speedup_MT": 4.924931422444954,
1074 + "rolling_sumsq@1000x3900_speedup_MT": 0.32161785435813445,
1075 + "realized_fused@1000x3900_cpuMT_ms": 2.279437379911542,
1076 + "realized_fused@1000x3900_metal_ms": 1.0434375144541264,
1077 + "tests": "pass / pass"
1078 + },
1079 + "M3BA24": {
1080 + "chip": "Apple M3",
1081 + "gpu_cores": 10,
1082 + "cpu_threads": "8",
1083 + "mem_gb": 24,
1084 + "macos": "26.5.1",
1085 + "cold_compile_s": 0.043905667,
1086 + "warm_compile_s": 0.000421292,
1087 + "realized_fused@1000x3900_speedup_MT": 2.687471016852494,
1088 + "regression_stats@1000x3900_speedup_MT": 1.6792771365359433,
1089 + "garch_nll_P64@1000x390_speedup_MT": 6.207505979251421,
1090 + "rolling_sumsq@1000x3900_speedup_MT": 0.3554353915980856,
1091 + "realized_fused@1000x3900_cpuMT_ms": 4.603916313499212,
1092 + "realized_fused@1000x3900_metal_ms": 1.7131036147475243,
1093 + "tests": "pass / pass"
1094 + },
1095 + "M3U96b": {
1096 + "chip": "Apple M3 Ultra",
1097 + "gpu_cores": 60,
1098 + "cpu_threads": "28",
1099 + "mem_gb": 96,
1100 + "macos": "26.4",
1101 + "cold_compile_s": 0.047089167,
1102 + "warm_compile_s": 0.000531084,
1103 + "realized_fused@1000x3900_speedup_MT": 1.6817560971796317,
1104 + "regression_stats@1000x3900_speedup_MT": 0.7767583073146588,
1105 + "garch_nll_P64@1000x390_speedup_MT": 3.179140922934574,
1106 + "rolling_sumsq@1000x3900_speedup_MT": 0.24312350847240793,
1107 + "realized_fused@1000x3900_cpuMT_ms": 2.304041408933699,
1108 + "realized_fused@1000x3900_metal_ms": 1.370021142065525,
1109 + "tests": "pass / pass"
1110 + },
1111 + "m4md": {
1112 + "chip": "Apple M4",
1113 + "gpu_cores": 10,
1114 + "cpu_threads": "10",
1115 + "mem_gb": 16,
1116 + "macos": "26.6.2",
1117 + "cold_compile_s": 0.042053541,
1118 + "warm_compile_s": 0.000386541,
1119 + "realized_fused@1000x3900_speedup_MT": 2.548863991558486,
1120 + "regression_stats@1000x3900_speedup_MT": 1.338401514661036,
1121 + "garch_nll_P64@1000x390_speedup_MT": 4.206244849053445,
1122 + "rolling_sumsq@1000x3900_speedup_MT": 0.37666800739402895,
1123 + "realized_fused@1000x3900_cpuMT_ms": 3.558958414942026,
1124 + "realized_fused@1000x3900_metal_ms": 1.3962920056656003,
1125 + "tests": "pass / pass"
1126 + },
1127 + "m4mm": {
1128 + "chip": "Apple M4 Pro",
1129 + "gpu_cores": 16,
1130 + "cpu_threads": "12",
1131 + "mem_gb": 48,
1132 + "macos": "26.5.1",
1133 + "cold_compile_s": 0.038549083,
1134 + "warm_compile_s": 0.000449708,
1135 + "realized_fused@1000x3900_speedup_MT": 1.6260083182113196,
1136 + "regression_stats@1000x3900_speedup_MT": 0.91166043986465,
1137 + "garch_nll_P64@1000x390_speedup_MT": 2.1391683174192333,
1138 + "rolling_sumsq@1000x3900_speedup_MT": 0.23880014056164212,
1139 + "realized_fused@1000x3900_cpuMT_ms": 2.68670788500458,
1140 + "realized_fused@1000x3900_metal_ms": 1.6523334197700024,
1141 + "tests": "pass / pass"
1142 + },
1143 + "M4M64c": {
1144 + "chip": "Apple M4 Max",
1145 + "gpu_cores": 40,
1146 + "cpu_threads": "16",
1147 + "mem_gb": 64,
1148 + "macos": "26.4",
1149 + "cold_compile_s": 0.040168875,
1150 + "warm_compile_s": 0.0004675,
1151 + "realized_fused@1000x3900_speedup_MT": 2.79582771769825,
1152 + "regression_stats@1000x3900_speedup_MT": 1.1902389066688093,
1153 + "garch_nll_P64@1000x390_speedup_MT": 4.8188331984067,
1154 + "rolling_sumsq@1000x3900_speedup_MT": 0.4781437102048132,
1155 + "realized_fused@1000x3900_cpuMT_ms": 2.066000597551465,
1156 + "realized_fused@1000x3900_metal_ms": 0.7389584789052606,
1157 + "tests": "pass / pass"
1158 + },
1159 + "m5ma": {
1160 + "chip": "Apple M5 Pro",
1161 + "gpu_cores": 16,
1162 + "cpu_threads": "15",
1163 + "mem_gb": 24,
1164 + "macos": "27.0",
1165 + "cold_compile_s": 0.043711542,
1166 + "warm_compile_s": 0.000386292,
1167 + "realized_fused@1000x3900_speedup_MT": 1.1284910996519257,
1168 + "regression_stats@1000x3900_speedup_MT": 0.5487957656812417,
1169 + "garch_nll_P64@1000x390_speedup_MT": 1.8287923928070076,
1170 + "rolling_sumsq@1000x3900_speedup_MT": 0.19530880040350074,
1171 + "realized_fused@1000x3900_cpuMT_ms": 2.040499937720597,
1172 + "realized_fused@1000x3900_metal_ms": 1.8081666203215718,
1173 + "tests": "pass / pass"
1174 + },
1175 + "M5M36": {
1176 + "chip": "Apple M5 Max",
1177 + "gpu_cores": 32,
1178 + "cpu_threads": "18",
1179 + "mem_gb": 36,
1180 + "macos": "27.0",
1181 + "cold_compile_s": 0.037059042,
1182 + "warm_compile_s": 0.000456708,
1183 + "realized_fused@1000x3900_speedup_MT": 1.1217974525711423,
1184 + "regression_stats@1000x3900_speedup_MT": 0.6015969625826116,
1185 + "garch_nll_P64@1000x390_speedup_MT": 2.1447918847693943,
1186 + "rolling_sumsq@1000x3900_speedup_MT": 0.22944356711535452,
1187 + "realized_fused@1000x3900_cpuMT_ms": 1.6108546406030655,
1188 + "realized_fused@1000x3900_metal_ms": 1.4359585475176573,
1189 + "tests": "pass / pass"
1190 + },
1191 + "m6ma": {
1192 + "chip": "Apple M6",
1193 + "gpu_cores": 12,
1194 + "cpu_threads": "12",
1195 + "mem_gb": 24,
1196 + "macos": "27.0",
1197 + "cold_compile_s": 0.039953334,
1198 + "warm_compile_s": 0.000306458,
1199 + "realized_fused@1000x3900_speedup_MT": 1.6330551240965197,
1200 + "regression_stats@1000x3900_speedup_MT": 0.7851066834472289,
1201 + "garch_nll_P64@1000x390_speedup_MT": 3.7206830701585027,
1202 + "rolling_sumsq@1000x3900_speedup_MT": 0.34461349554716936,
1203 + "realized_fused@1000x3900_cpuMT_ms": 2.4681249633431435,
1204 + "realized_fused@1000x3900_metal_ms": 1.5113543486222625,
1205 + "tests": "pass / pass"
1206 + }
1207 + },
1208 + "laptop": {
1209 + "chip": "Apple M5 Max",
1210 + "os": "27.0",
1211 + "xcode": "Xcode 27.2 Build version 27B52",
1212 + "clang": "Apple clang version 21.0.0 (clang-2100.4.1.1)",
1213 + "cmake": "cmake version 4.3.2",
1214 + "metal_toolchain": "Apple metal version 32023.922 (metalfe-32023.922.4)",
1215 + "brew": {
1216 + "eigen": "eigen 5.0.1",
1217 + "apache-arrow": "apache-arrow 26.0.0_3",
1218 + "catch2": "catch2 3.16.1",
1219 + "nlohmann-json": "nlohmann-json 3.12.0",
1220 + "openblas": "openblas 0.3.33",
1221 + "libomp": "libomp 22.1.8"
1222 + },
1223 + "load_avg": "{ 3,67 3,00 2,56 }",
1224 + "thermal": "Note: No thermal warning level has been recorded;Note: No performance warning level has been recorded;Note: No CPU power status has been recorded;",
1225 + "ncpu": "18",
1226 + "perf_cores": "6",
1227 + "eff_cores": "12"
1228 + },
1229 + "generated_at": "2026-11-02T21:05:20.158901+00:00"
1230 +}
\ No newline at end of file
added experiments/scripts/make_paper_assets.py +166 −0
@@ -0,0 +1,166 @@
1 +#!/usr/bin/env python3
2 +"""Generates every paper table (paper/tables/*.tex) and figure (paper/figures/*.pdf) from the tracked artifacts under
3 +experiments/results/, and writes experiments/results/key_numbers.json (the only source of numbers quoted in the prose)
4 +and experiments/manifests/paper_assets.json (SHA-256 of every input and output). No number is typed by hand."""
5 +import os, sys, json, glob, hashlib, collections, statistics, csv
6 +import numpy as np
7 +ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".."); RES = os.path.join(ROOT, "experiments", "results"); RAW = os.path.join(RES, "raw")
8 +TAB = os.path.join(ROOT, "paper", "tables"); FIG = os.path.join(ROOT, "paper", "figures"); os.makedirs(TAB, exist_ok=True); os.makedirs(FIG, exist_ok=True)
9 +import matplotlib; matplotlib.use("Agg"); import matplotlib.pyplot as plt
10 +plt.rcParams.update({"font.size": 8, "axes.titlesize": 9, "legend.fontsize": 7, "figure.dpi": 150})
11 +COL = {"cpu1": "#9aa0a6", "cpuN": "#1f4e79", "metal": "#c0392b", "metal_unfused": "#e67e22", "pandas": "#7f8c8d", "polars": "#2980b9", "duckdb": "#27ae60", "raid_cpu": "#1f4e79", "raid_metal": "#c0392b"}
12 +rng = np.random.default_rng(20261102); key = {}; inputs = {}; outputs = {}
13 +def sha(p): return hashlib.sha256(open(p, "rb").read()).hexdigest()
14 +def load(name):
15 + p = os.path.join(RAW, name);
16 + if not os.path.exists(p): return []
17 + inputs[name] = sha(p); return [json.loads(l) for l in open(p) if l.strip()]
18 +def ci(x, n=2000): x = np.asarray(x, float); m = [np.median(rng.choice(x, x.size, replace=True)) for _ in range(n)]; return float(np.median(x)), float(np.percentile(m, 2.5)), float(np.percentile(m, 97.5))
19 +def med(it):
20 + v = [x for x in it if x is not None and np.isfinite(x)]; return statistics.median(v) if v else None
21 +def fmt(x, d=2): return "--" if x is None or (isinstance(x, float) and not np.isfinite(x)) else f"{x:.{d}f}"
22 +def write(name, s): p = os.path.join(TAB, name); open(p, "w").write(s); outputs["tables/" + name] = sha(p)
23 +def savefig(fig, name): p = os.path.join(FIG, name); fig.savefig(p, bbox_inches="tight"); plt.close(fig); outputs["figures/" + name] = sha(p)
24 +
25 +# ---------------------------------------------------------------- primitives (laptop)
26 +prim = [r for r in load("bench_primitives.jsonl") if r.get("kernel") != "shader_library_load"]
27 +g = collections.defaultdict(list)
28 +for r in prim: g[(r["kernel"], r["S"], r["n"], r["backend"], r["threads"] == 1)].append(r["wall_seconds"])
29 +rows = {k: ci(v) for k, v in g.items()}
30 +def spd(k, S, n):
31 + c = rows.get((k, S, n, "cpu", False)); m = rows.get((k, S, n, "metal", False)); c1 = rows.get((k, S, n, "cpu", True))
32 + if not c or not m: return None
33 + verdict = "Metal" if m[2] < c[1] else ("CPU" if c[2] < m[1] else "tie"); return (c1[0] if c1 else None, c[0], m[0], c[0] / m[0], verdict)
34 +lines = [r"\begin{tabular}{llrrrrrl}", r"\toprule", r"Kernel & $S\times n$ & elements & CPU 1T (ms) & CPU MT (ms) & Metal (ms) & speedup & verdict \\", r"\midrule"]
35 +prim_key = {}
36 +for k in ["realized_fused", "regression_stats", "rolling_sumsq", "garch_nll_P1", "garch_nll_P64"]:
37 + for (S, n) in sorted({(r["S"], r["n"]) for r in prim if r["kernel"] == k}, key=lambda t: (t[0] * t[1], t[0])):
38 + s = spd(k, S, n)
39 + if not s: continue
40 + prim_key[f"{k}@{S}x{n}"] = {"cpu1_ms": None if s[0] is None else 1e3 * s[0], "cpuMT_ms": 1e3 * s[1], "metal_ms": 1e3 * s[2], "speedup": s[3], "verdict": s[4]}
41 + lines.append(f"{k.replace('_', r'\_')} & ${S}\\times{n}$ & {S * n:,} & {fmt(None if s[0] is None else 1e3 * s[0], 3)} & {fmt(1e3 * s[1], 3)} & {fmt(1e3 * s[2], 3)} & {fmt(s[3])} & {s[4]} \\\\")
42 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_primitives.tex", "\n".join(lines)); key["primitives"] = prim_key
43 +# break-even summary
44 +be = {}
45 +for k in ["realized_fused", "regression_stats", "rolling_sumsq", "garch_nll_P1", "garch_nll_P64"]:
46 + wins = sorted(v["cpuMT_ms"] and (int(t.split("@")[1].split("x")[0]) * int(t.split("x")[1])) for t, v in prim_key.items() if t.startswith(k + "@") and v["verdict"] == "Metal")
47 + losses = sorted((int(t.split("@")[1].split("x")[0]) * int(t.split("x")[1])) for t, v in prim_key.items() if t.startswith(k + "@") and v["verdict"] == "CPU")
48 + be[k] = {"smallest_metal_win": wins[0] if wins else None, "largest_cpu_win": losses[-1] if losses else None, "max_speedup": max(v["speedup"] for t, v in prim_key.items() if t.startswith(k + "@")), "min_speedup": min(v["speedup"] for t, v in prim_key.items() if t.startswith(k + "@"))}
49 +key["breakeven"] = be
50 +# figure: throughput
51 +kernels = ["realized_fused", "regression_stats", "rolling_sumsq", "garch_nll_P64"]; fig, axes = plt.subplots(1, 4, figsize=(10, 2.6))
52 +for ax, k in zip(axes, kernels):
53 + for be_, one, lab in [("cpu", True, "CPU 1 thread"), ("cpu", False, "CPU 18 threads"), ("metal", False, "Metal")]:
54 + pts = sorted([(S * n, S * n / rows[(k, S, n, be_, one)][0]) for (kk, S, n, b, o) in rows if kk == k and b == be_ and o == one])
55 + if pts: ax.plot([p[0] for p in pts], [p[1] for p in pts], "o-", ms=2.5, lw=1, color=COL["cpu1" if one else ("cpuN" if be_ == "cpu" else "metal")], label=lab)
56 + ax.set_xscale("log"); ax.set_yscale("log"); ax.set_title(k.replace("_", " ")); ax.set_xlabel("elements"); ax.grid(alpha=.3)
57 +axes[0].set_ylabel("elements / s (median)"); axes[0].legend(); savefig(fig, "fig_primitives_throughput.pdf")
58 +
59 +# ---------------------------------------------------------------- E1
60 +e1 = [r for r in load("e1_batched_rv.jsonl") if r.get("kind") == "bench"]
61 +g1 = collections.defaultdict(list)
62 +for r in e1: g1[(r["source"], r["S"], r["segment"], r["backend"])].append(r["wall_seconds"])
63 +r1 = {k: ci(v) for k, v in g1.items()}; err = collections.defaultdict(list)
64 +for r in e1:
65 + if r["backend"].startswith("metal"): err[(r["source"], r["S"], r["segment"])].append(r["max_rel_err_rv_vs_fp64"])
66 +lines = [r"\begin{tabular}{llrrrrrrl}", r"\toprule", r"Panel & $S$ & segment & elements & CPU 1T (ms) & CPU MT (ms) & Metal fused (ms) & Metal 4 kernels (ms) & max rel.\ err.\ RV \\", r"\midrule"]
67 +e1_key = {}
68 +for (src, S, seg) in sorted({(r["source"], r["S"], r["segment"]) for r in e1}, key=lambda t: (t[0] != "real", t[1], ["day", "week", "month", "year"].index(t[2]))):
69 + el = next(r["elements"] for r in e1 if (r["source"], r["S"], r["segment"]) == (src, S, seg))
70 + c1, cn, mt, mu = (r1.get((src, S, seg, b)) for b in ["cpu1", "cpuN", "metal", "metal_unfused"]); mx = max(err[(src, S, seg)]) if err[(src, S, seg)] else None
71 + e1_key[f"{src}_S{S}_{seg}"] = {"elements": el, "cpu1_ms": c1 and 1e3 * c1[0], "cpuMT_ms": cn and 1e3 * cn[0], "metal_ms": mt and 1e3 * mt[0], "metal_unfused_ms": mu and 1e3 * mu[0], "speedup_MT": (cn and mt) and cn[0] / mt[0], "fusion_gain": (mu and mt) and mu[0] / mt[0], "max_rel_err": mx, "metal_wins": bool(cn and mt and mt[2] < cn[1]), "cpu_wins": bool(cn and mt and cn[2] < mt[1])}
72 + lines.append(f"{src} & {S} & {seg} & {el:,} & {fmt(c1 and 1e3 * c1[0], 2)} & {fmt(cn and 1e3 * cn[0], 2)} & {fmt(mt and 1e3 * mt[0], 2)} & {fmt(mu and 1e3 * mu[0], 2)} & {('%.1e' % mx) if mx is not None else '--'} \\\\")
73 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e1.tex", "\n".join(lines)); key["E1"] = e1_key
74 +fig, axes = plt.subplots(1, 2, figsize=(7, 2.6))
75 +for ax, src in zip(axes, ["real", "synthetic"]):
76 + for b, lab in [("cpu1", "CPU 1T"), ("cpuN", "CPU 18T"), ("metal", "Metal fused"), ("metal_unfused", "Metal 4 kernels")]:
77 + pts = sorted([(e1_key[k]["elements"], e1_key[k]["elements"] / (e1_key[k][{"cpu1": "cpu1_ms", "cpuN": "cpuMT_ms", "metal": "metal_ms", "metal_unfused": "metal_unfused_ms"}[b]] / 1e3)) for k in e1_key if k.startswith(src + "_") and e1_key[k][{"cpu1": "cpu1_ms", "cpuN": "cpuMT_ms", "metal": "metal_ms", "metal_unfused": "metal_unfused_ms"}[b]]])
78 + if pts: ax.plot([p[0] for p in pts], [p[1] for p in pts], "o", ms=3, color=COL[b], label=lab)
79 + ax.set_xscale("log"); ax.set_yscale("log"); ax.set_title(f"E1 — {src} panel"); ax.set_xlabel("elements (returns)"); ax.grid(alpha=.3)
80 +axes[0].set_ylabel("returns / s"); axes[0].legend(); savefig(fig, "fig_e1.pdf")
81 +
82 +# ---------------------------------------------------------------- E2
83 +e2 = load("e2_har.jsonl"); acc = [r for r in e2 if r.get("kind") == "accuracy"]; rt = [r for r in e2 if r.get("kind") == "runtime"]
84 +lines = [r"\begin{tabular}{lrrrrrr}", r"\toprule", r"$h$ & symbols & HAR QLIKE & log-HAR QLIKE & HARQ QLIKE & RW QLIKE & HAR beats RW (\%) \\", r"\midrule"]; e2_key = {}
85 +for h in [1, 5, 22]:
86 + rs = [r for r in acc if r["h"] == h and "qlike" in r.get("har", {})]
87 + medq = lambda m: med(r[m]["qlike"] for r in rs if "qlike" in r.get(m, {}))
88 + beats = 100 * np.mean([r["har"]["qlike"] < r["random_walk"]["qlike"] for r in rs])
89 + e2_key[f"h{h}"] = {"n": len(rs), "har": medq("har"), "loghar": medq("loghar"), "harq": medq("harq"), "rw": medq("random_walk"), "har_beats_rw_pct": beats, "fits_per_symbol": med(r["har"]["fits"] for r in rs)}
90 + lines.append(f"{h} & {len(rs)} & {fmt(medq('har'), 3)} & {fmt(medq('loghar'), 3)} & {fmt(medq('harq'), 3)} & {fmt(medq('random_walk'), 3)} & {fmt(beats, 1)} \\\\")
91 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e2_accuracy.tex", "\n".join(lines))
92 +g2 = collections.defaultdict(list)
93 +for r in rt: g2[(r["S"], r["mode"])].append(r["wall_seconds"])
94 +lines = [r"\begin{tabular}{rrrrrr}", r"\toprule", r"$S$ & $T$ & per-series 1T (ms) & per-series 18T (ms) & batched CPU (ms) & batched Metal (ms) \\", r"\midrule"]; e2_rt = {}
95 +for S in sorted({r["S"] for r in rt}):
96 + T = next(r["T_per_series"] for r in rt if r["S"] == S); v = {m: ci(g2[(S, m)])[0] for m in ["per_series_cpu1", "per_series_cpuMT", "batched_cpu", "batched_metal"] if g2[(S, m)]}
97 + e2_rt[str(S)] = {**{k: 1e3 * x for k, x in v.items()}, "T": T}; lines.append(f"{S} & {T} & " + " & ".join(fmt(1e3 * v.get(m), 3) if v.get(m) else "--" for m in ["per_series_cpu1", "per_series_cpuMT", "batched_cpu", "batched_metal"]) + r" \\")
98 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e2_runtime.tex", "\n".join(lines)); key["E2"] = {"accuracy": e2_key, "runtime": e2_rt}
99 +
100 +# ---------------------------------------------------------------- E3
101 +e3 = load("e3_garch.jsonl"); fits = [r for r in e3 if r.get("kind") == "fit"]; grid = [r for r in e3 if r.get("kind") == "grid"]; loadrec = next((r for r in e3 if r.get("kind") == "load"), {})
102 +lines = [r"\begin{tabular}{lrrrrrrr}", r"\toprule", r"Model & fits & converged (\%) & median iterations & median time (ms) & median persistence & QLIKE vs RV & QLIKE RW \\", r"\midrule"]; e3_key = {"symbols": loadrec.get("symbols"), "daily_history": loadrec.get("daily_history_replaced")}
103 +for m in ["garch.n", "gjr.n", "egarch.n", "garch.t"]:
104 + rs = [r for r in fits if r["model"] == m]; ok = [r for r in rs if r.get("converged")]
105 + e3_key[m] = {"n": len(rs), "converged_pct": 100 * len(ok) / len(rs), "median_iter": med(r["iterations"] for r in ok), "median_ms": 1e3 * med(r["seconds"] for r in ok), "median_persistence": med(r["persistence"] for r in ok), "qlike": med(r.get("qlike_vs_rv") for r in ok), "qlike_rw": med(r.get("qlike_rw_rv") for r in ok), "n_train": med(r["n_train"] for r in rs), "n_eval": sum(1 for r in ok if r.get("qlike_vs_rv") is not None)}
106 + k3 = e3_key[m]; lines.append(f"{m} & {k3['n']} & {fmt(k3['converged_pct'], 1)} & {fmt(k3['median_iter'], 0)} & {fmt(k3['median_ms'], 2)} & {fmt(k3['median_persistence'], 3)} & {fmt(k3['qlike'], 3)} & {fmt(k3['qlike_rw'], 3)} \\\\")
107 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e3_fits.tex", "\n".join(lines))
108 +gm = [r for r in grid if r["backend"] == "metal"]; gc = [r for r in grid if r["backend"] == "cpuMT"]
109 +if gm and gc: e3_key["grid"] = {"S": gm[0]["S"], "P": gm[0]["P"], "cpuMT_ms": 1e3 * statistics.median(r["wall_seconds"] for r in gc), "metal_ms": 1e3 * statistics.median(r["wall_seconds"] for r in gm), "max_rel_err_nll": max(r["max_rel_err_nll"] for r in gm), "argmin_agreement": gm[0]["argmin_agreement"], "argmin_total": gm[0]["S_total"]}
110 +key["E3"] = e3_key
111 +
112 +# ---------------------------------------------------------------- E4
113 +e4 = load("e4_connectedness.jsonl"); lines = [r"\begin{tabular}{rrrrrrrr}", r"\toprule", r"$N$ & days used & cond.\ median & cond.\ max & LW shrinkage & DY windows (120 d) & mean total (\%) & time (ms) \\", r"\midrule"]; e4_key = {}
114 +for N in sorted({r["N"] for r in e4}):
115 + rc = next((r for r in e4 if r["kind"] == "rcov" and r["N"] == N), None); dy = [r for r in e4 if r["kind"] == "dy" and r["N"] == N and r.get("window") == 120 and "wall_seconds" in r]
116 + if rc: e4_key[str(N)] = {"days_ok": rc["days_ok"], "days_skipped": rc["days_skipped"], "cond_median": rc["cond_median"], "cond_max": rc["cond_max"], "lw": rc["ledoit_wolf_shrinkage_mean"], "dy_windows": dy[0]["n_windows"] if dy else None, "dy_total": dy[0]["mean_total"] if dy else None, "dy_ms": 1e3 * statistics.median(r["wall_seconds"] for r in dy) if dy else None, "dy_failures": dy[0]["failures"] if dy else None}
117 + k4 = e4_key.get(str(N), {}); lines.append(f"{N} & {k4.get('days_ok', '--')} & {fmt(k4.get('cond_median'), 0)} & {fmt(k4.get('cond_max'), 0)} & {fmt(k4.get('lw'), 2)} & {k4.get('dy_windows', '--')} & {fmt(k4.get('dy_total'), 1)} & {fmt(k4.get('dy_ms'), 1)} \\\\")
118 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e4.tex", "\n".join(lines)); key["E4"] = e4_key
119 +
120 +# ---------------------------------------------------------------- E5
121 +e5 = load("e5_inference.jsonl"); lines = [r"\begin{tabular}{llrrrr}", r"\toprule", r"DGP & parameter & bias & RMSE & coverage 95\% & converged \\", r"\midrule"]; e5_key = {}
122 +for r in e5:
123 + if r["kind"] == "garch_mc":
124 + e5_key[f"garch_n{r['n']}"] = {p: r[p] for p in ["mu", "omega", "alpha", "beta"]} | {"converged": r["converged"], "R": r["R"]}
125 + for p in ["mu", "omega", "alpha", "beta"]: lines.append(f"GARCH(1,1) $n={r['n']}$ & $\\{p}$ & {r[p]['bias']:+.4f} & {fmt(r[p]['rmse'], 4)} & {fmt(r[p]['coverage95'], 3)} & {r['converged']}/{r['R']} \\\\")
126 + elif r["kind"] == "har_mc":
127 + e5_key[f"har_h{r['h']}"] = r["coverage95"]; lines.append(f"HAR $h={r['h']}$ (HAC) & $\\beta_0,\\beta_d,\\beta_w,\\beta_m$ & -- & -- & {', '.join(fmt(c, 3) for c in r['coverage95'])} & {r['R']}/{r['R']} \\\\")
128 + elif r["kind"] in ("repro_bootstrap", "repro_realized"): e5_key[r["kind"]] = {k: v for k, v in r.items() if k not in ("kind", "experiment")}
129 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e5.tex", "\n".join(lines)); key["E5"] = e5_key
130 +
131 +# ---------------------------------------------------------------- E6
132 +e6 = load("e6_pipeline.jsonl"); e6b = load("e6_baselines.jsonl"); g6 = collections.defaultdict(list); st6 = collections.defaultdict(list)
133 +for r in e6: g6["RAID " + r["backend_used"]].append(r["total_seconds"]); st6["read"].append(r["read_seconds"]); st6["prep"].append(r["prep_seconds"]); st6["est_" + r["backend_used"]].append(r["estimate_seconds"]); st6["rss_" + r["backend_used"]].append(r["peak_rss_after"]); st6["bars"].append(r["bars"])
134 +for r in e6b: g6[r["engine"]].append(r["total_seconds"]); st6["rss_" + r["engine"]].append(r["peak_rss"])
135 +lines = [r"\begin{tabular}{lrrrl}", r"\toprule", r"Engine & median total (s) & 95\% CI & bars / s & notes \\", r"\midrule"]; e6_key = {"bars_per_file": statistics.median(st6["bars"]), "read_s": statistics.median(st6["read"]), "prep_s": statistics.median(st6["prep"]), "est_cpu_s": statistics.median(st6["est_cpu"]), "est_metal_s": statistics.median(st6["est_metal"]) if st6["est_metal"] else None}
136 +notes = {"RAID cpu": "Arrow projection, exact calendar, 5 measures", "RAID metal": "same, fused Metal kernel", "pandas": "approximate early-close rule, groupby.apply", "polars": "approximate early-close rule, lazy scan", "duckdb": "approximate early-close rule, SQL window"}
137 +for eng in ["RAID cpu", "RAID metal", "polars", "duckdb", "pandas"]:
138 + if not g6[eng]: continue
139 + m, lo, hi = ci(g6[eng]); e6_key[eng] = {"median_s": m, "ci": [lo, hi], "bars_per_s": e6_key["bars_per_file"] / m}; lines.append(f"{eng} & {fmt(m, 3)} & [{fmt(lo, 3)}, {fmt(hi, 3)}] & {e6_key['bars_per_file'] / m / 1e6:.1f}M & {notes[eng]} \\\\")
140 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e6.tex", "\n".join(lines)); key["E6"] = e6_key
141 +
142 +# ---------------------------------------------------------------- E7
143 +e7 = json.load(open(os.path.join(RES, "e7_summary.json"))) if os.path.exists(os.path.join(RES, "e7_summary.json")) else []
144 +inputs["e7_summary.json"] = sha(os.path.join(RES, "e7_summary.json")) if e7 else None
145 +lines = [r"\begin{tabular}{llrrrllrrrr}", r"\toprule", r"Node & chip & GPU cores & CPU thr. & GB & tests (metallib / runtime) & cold / warm compile (ms) & RV fused $1000\times3900$ speedup & regression speedup & GARCH P=64 speedup & rolling speedup \\", r"\midrule"]; e7_key = {}
146 +order = ["m2m8a", "M2M32c", "M2U64", "M3BA24", "M3U96b", "m4md", "m4mm", "M4M64c", "m5ma", "M5M36", "m6ma"]
147 +for n in order:
148 + r = next((x for x in e7 if x.get("node") == n), None)
149 + if not r: continue
150 + t = ("pass" if r["tests_metallib"].startswith("All tests passed") else "FAIL") + " / " + ("pass" if r["tests_runtime_msl"].startswith("All tests passed") else "FAIL")
151 + e7_key[n] = {k: r.get(k) for k in ["chip", "gpu_cores", "cpu_threads", "mem_gb", "macos", "cold_compile_s", "warm_compile_s", "realized_fused@1000x3900_speedup_MT", "regression_stats@1000x3900_speedup_MT", "garch_nll_P64@1000x390_speedup_MT", "rolling_sumsq@1000x3900_speedup_MT", "realized_fused@1000x3900_cpuMT_ms", "realized_fused@1000x3900_metal_ms"]} | {"tests": t}
152 + lines.append(f"{n} & {r['chip']} & {r['gpu_cores']} & {r['cpu_threads']} & {r['mem_gb']} & {t} & {fmt(1e3 * (r['cold_compile_s'] or 0), 0)} / {fmt(1e3 * (r['warm_compile_s'] or 0), 0)} & {fmt(r['realized_fused@1000x3900_speedup_MT'])} & {fmt(r['regression_stats@1000x3900_speedup_MT'])} & {fmt(r['garch_nll_P64@1000x390_speedup_MT'])} & {fmt(r['rolling_sumsq@1000x3900_speedup_MT'])} \\\\")
153 +lines += [r"\bottomrule", r"\end{tabular}"]; write("tab_e7.tex", "\n".join(lines)); key["E7"] = e7_key
154 +fig, ax = plt.subplots(figsize=(6, 2.8)); xs = [e7_key[n]["gpu_cores"] for n in e7_key];
155 +for k, lab, c in [("realized_fused@1000x3900_speedup_MT", "RV fused 1000×3900", COL["metal"]), ("garch_nll_P64@1000x390_speedup_MT", "GARCH NLL P=64 1000×390", COL["cpuN"]), ("rolling_sumsq@1000x3900_speedup_MT", "rolling sumsq 1000×3900", COL["cpu1"])]:
156 + ax.scatter([e7_key[n]["gpu_cores"] for n in e7_key], [e7_key[n][k] for n in e7_key], label=lab, color=c, s=18)
157 +for n in e7_key: ax.annotate(e7_key[n]["chip"].replace("Apple ", ""), (e7_key[n]["gpu_cores"], e7_key[n]["realized_fused@1000x3900_speedup_MT"]), fontsize=6, xytext=(2, 2), textcoords="offset points")
158 +ax.axhline(1, color="k", lw=.6, ls="--"); ax.set_xlabel("GPU cores"); ax.set_ylabel("Metal / CPU-MT speedup"); ax.set_yscale("log"); ax.grid(alpha=.3); ax.legend(); savefig(fig, "fig_e7.pdf")
159 +
160 +# ---------------------------------------------------------------- hardware inventory + manifest
161 +env = glob.glob(os.path.join(ROOT, "experiments", "manifests", "environment_*.json")); envj = json.load(open(env[0])) if env else {}
162 +key["laptop"] = {k: envj.get(k) for k in ["chip", "os", "xcode", "clang", "cmake", "metal_toolchain", "brew", "load_avg", "thermal", "ncpu", "perf_cores", "eff_cores"]}
163 +key["generated_at"] = __import__("datetime").datetime.now(__import__("datetime").timezone.utc).isoformat()
164 +json.dump(key, open(os.path.join(RES, "key_numbers.json"), "w"), indent=1)
165 +json.dump({"inputs": inputs, "outputs": outputs, "key_numbers_sha256": sha(os.path.join(RES, "key_numbers.json"))}, open(os.path.join(ROOT, "experiments", "manifests", "paper_assets.json"), "w"), indent=1)
166 +print("tables:", sorted(outputs)); print(json.dumps({k: key[k] for k in ["breakeven", "E6"]}, indent=1)[:1500])
added experiments/scripts/run_e1_e2_e3.sh +7 −0
@@ -0,0 +1,7 @@
1 +#!/bin/bash
2 +set -uo pipefail; cd "$(dirname "$0")/../.."; R=experiments/results/raw; E0=experiments/results/e0_universe.json
3 +rm -f $R/e1_batched_rv.jsonl $R/e2_har.jsonl $R/e3_garch.jsonl
4 +echo "== E1 $(date)"; ./build/macos-release/bench_bench_e1_batched_rv $E0 $R/e1_batched_rv.jsonl 5 2> $R/e1.log; echo "E1 exit=$?"
5 +echo "== E2 $(date)"; ./build/macos-release/bench_bench_e2_har $E0 $R/e2_har.jsonl 5 2> $R/e2.log; echo "E2 exit=$?"
6 +echo "== E3 $(date)"; ./build/macos-release/bench_bench_e3_garch $E0 $R/e3_garch.jsonl 1000 experiments/results/e0_daily.json 2> $R/e3.log; echo "E3 exit=$?"
7 +echo "== done $(date)"
modified include/raid/estimators/realized.hpp +1 −0
@@ -25,6 +25,7 @@ namespace raid::est {
25 25 struct RealizedOptions {
26 26 bool bpv_finite_sample{true};
27 27 bool fuse_kernels{true}; // Metal: one fused pass for all accumulators (ablation: false → 4 kernels)
28 + bool tripower{true}; // tripower quarticity (CPU FP64, parallel over segments; |x|^{4/3} computed once per element)
28 29 bool annualize{false}; // multiply variances by `periods_per_year`
29 30 f64 periods_per_year{252.0};
30 31 ExecutionPlan plan{};
added paper/appendices/appendix.tex +46 −0
@@ -0,0 +1,46 @@
1 +\begin{appendices}
2 +\section{Kernel pseudocode}
3 +\label{app:kernels}
4 +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
5 +df two_sum(float a, float b): s = a + b; bb = s - a; e = (a - (s - bb)) + (b - bb); return (s, e)
6 +df df_add_f(df a, float v): (h, l) = two_sum(a.hi, v); l += a.lo; h2 = h + l; return (h2, l - (h2 - h))
7 +kernel realized_fused(x, chunks, out): // one threadgroup (256 threads) per (segment, chunk)
8 + c = chunks[gid]; s2 = adj = neg = pos = s4 = (0, 0)
9 + for i in c.begin + lid .. c.end step 256:
10 + v = x[i]; q = v*v; s2 += q; s4 += q*q; if v < 0: neg += q elif v > 0: pos += q
11 + if i > c.begin: adj += |v| * |x[i-1]|
12 + tree-reduce each df over the threadgroup in fixed order; thread 0 writes 5 float2
13 +host: for each chunk c of segment s: acc[s] += (double)hi + (double)lo (fixed order);
14 + adj[s] += |x[c.begin]| * |x[c.begin-1]| in FP64 when c.begin > segment begin
15 +kernel garch_nll(r, seg, params[8], var0, jobs, out, model): // one thread per (segment, parameter vector)
16 + (mu, omega, alpha, gamma, beta, nu, kconst, Eabs) = params[job]; s2 = var0[seg]
17 + validity checks -> +inf; nll = (0, 0); e_prev = r[b] - mu
18 + for i in 0..n-1: if i > 0: s2 = recursion(model); if !(s2 > 0): return +inf
19 + e = r[b+i] - mu; ll = kconst - 0.5 log s2 - (student ? 0.5 (nu+1) log(1 + e^2/((nu-2) s2)) : 0.5 e^2/s2)
20 + nll += -ll
21 + out[job] = nll.hi + nll.lo // host adds n log(sd) for the per-series scaling
22 +\end{lstlisting}
23 +
24 +\section{Optimiser details}
25 +GARCH-family QML: parameters are transformed to an unconstrained space ($\omega = e^{u}$; persistence $p = \sigma(u_p)(1-10^{-9})$ and share $s = \sigma(u_s)$ so that $\alpha = sp$, $\beta = (1-s)p$ for GARCH; for GJR $\alpha+\gamma = e^{u_g}$ and $\beta = p - \alpha - \gamma/2 \ge 0$; for EGARCH $\omega$ free and $\beta = \tanh(u)$; $\nu = 2.05 + 497.95\,\sigma(u_\nu)$). BFGS with Armijo backtracking (factor 0.5, up to 60 halvings), central-difference gradients with step $10^{-5}\max(1,|u|)$, convergence when $\|g\| < 10^{-5}$, or when the relative change of the negative log-likelihood is below $10^{-8}$ (or the step below $10^{-9}$) with $\|g\| < 10^{-2}$ in the transformed space; at most 500 iterations; up to three starting variants (persistence 0.95, 0.80, 0.985; opposite EGARCH $\gamma$ sign). Covariance from the numerical Hessian (central differences, step $10^{-4}\max(1,|\theta|)$) and the OPG of per-observation scores. Returns are scaled to unit variance before optimisation and the estimates un-scaled (EGARCH: $\omega \to \omega + (1-\beta)\log s^{-2}$).
26 +
27 +\section{Finite-sample conventions}
28 +Regular session = 09:30 to 16:00 ET inclusive of the 16:00 closing print (391 one-minute bars; 211 on 13:00 early closes); extended session 04:00--19:59 ET (17:00 on early closes). Intraday returns are close-to-close within the session ($M = $ bars $-1$). BPV factor $M/(M-1)$ on by default; TriPV factor $M/(M-2)$; RQ $= (M/3)\sum r^4$. HAR windows of 1, 5 and 22 trading days; targets averaged over $h$ sessions; HAC lags $\max(h-1, \lfloor 4(n/100)^{2/9}\rfloor)$. HARQ regressor $(\sqrt{\RQ_t} - \sqrt{\overline{\RQ}})\RV_t$ with $\overline{\RQ}$ over the estimation sample. GARCH $\sigma_0^2$ = sample variance of $\varepsilon$. Stationary bootstrap mean block $n^{1/3}$ unless stated.
29 +
30 +\section{Benchmark configuration}
31 +Laptop: Apple M5 Max (6P+12E cores reported by \texttt{hw.perflevel}, 18 hardware threads), 40-core GPU, 48\,GB, macOS 27.0 (26A5425a), Xcode 27.2 (27B52), Apple clang 21.0.0 (clang-2100.4.1.1), Metal toolchain 32023.922, CMake 4.3.2, \texttt{-O3 -mcpu=native -ffp-model=precise}, Eigen 5.0.1 + Accelerate, Arrow 26.0.0. Metal: 256-thread threadgroups for reductions, 4\,096-element chunks, 64-thread threadgroups for GARCH jobs, shared storage mode, \texttt{fastMathEnabled = NO}. Repetitions: 5 (laptop), 3 (nodes); 2 warm-ups; shuffled order with seed 20261102; medians and 2\,000-draw bootstrap 95\,\% CIs. Cluster bundle: \texttt{-mcpu=apple-m1}, deployment target macOS 26.0, Arrow disabled, Metal enabled, prebuilt metallib plus embedded MSL.
32 +
33 +\section{Hardware inventory (E7)}
34 +\begin{center}\scriptsize
35 +\begin{tabular}{llrrrl}
36 +\toprule Node & Chip & GPU cores & CPU threads & RAM (GB) & macOS \\ \midrule
37 +m2m8a & Apple M2 & 10 & 8 & 8 & 26.5.1 \\ M2M32c & Apple M2 Max & 30 & 12 & 32 & 26.5.1 \\ M2U64 & Apple M2 Ultra & 60 & 24 & 64 & 26.5 \\ M3BA24 & Apple M3 & 10 & 8 & 24 & 26.5.1 \\ M3U96b & Apple M3 Ultra & 60 & 28 & 96 & 26.4 \\ m4md & Apple M4 & 10 & 10 & 16 & 26.6.2 \\ m4mm & Apple M4 Pro & 16 & 12 & 48 & 26.5.1 \\ M4M64c & Apple M4 Max & 40 & 16 & 64 & 26.4 \\ m5ma & Apple M5 Pro & 16 & 15 & 24 & 27.0 \\ M5M36 & Apple M5 Max & 32 & 18 & 36 & 27.0 \\ m6ma & Apple M6 & 12 & 12 & 24 & 27.0 \\ \bottomrule
38 +\end{tabular}
39 +\end{center}
40 +
41 +\section{API provenance}
42 +FinData OS API \texttt{https://findata.spboucher.ai/api/v1} (OpenAPI 3.1 snapshot of 2026-11-02 in \texttt{docs/evidence/}); datasets \texttt{market\_bars.stock.1m.raw} (version 17\,375 at export time; 6.70 billion rows, 16\,195 symbols, 2000--2026) and \texttt{market\_bars.stock.1d.raw}; bars schema v1 (\texttt{timestamp\_utc} = bar open, UTC); exports as Parquet with the dataset version in the job record; request identifiers of every exchange are kept in the cache manifests; API key identified by a SHA-256 fingerprint only. Data © FirstRate Data, private-use licence, no redistribution.
43 +
44 +\section{Numerical tolerance tables}
45 +See Table~\ref{tab:validation} for the reference tolerances. GPU/CPU tolerances by primitive: realized accumulators $10^{-6}$ relative ($\Sigma x^4$: $10^{-5}$); rolling sums $10^{-5}$; regression statistics $10^{-6}$ absolute on $\max(1,|\cdot|)$ and $10^{-5}$ on the solved coefficients; batched GARCH NLL $2\times10^{-5}$ relative (Student-$t$: $5\times10^{-5}$) on simulated series with $n = 2\,000$; on the E3 real-data grid the maximum relative difference is $2\times10^{-3}$ at boundary grid points and the argmin agrees for 888/888 series.
46 +\end{appendices}
added paper/figures/fig_e1.pdf +0 −0

Binary file not shown.

added paper/figures/fig_e7.pdf +0 −0

Binary file not shown.

added paper/figures/fig_primitives_throughput.pdf +0 −0

Binary file not shown.

added paper/sections/applications.tex +37 −0
Large diff (37 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/architecture.tex +34 −0
Large diff (34 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/conclusion.tex +6 −0
Large diff (6 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/correctness.tex +41 −0
Large diff (41 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/endtoend.tex +26 −0
Large diff (26 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/estimators.tex +38 −0
Large diff (38 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/metal.tex +16 −0
Large diff (16 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/microbenchmarks.tex +36 −0
Large diff (36 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/reproducibility.tex +8 −0
Large diff (8 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/setup.tex +12 −0
Large diff (12 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/threats.tex +12 −0
Large diff (12 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e1.tex +25 −0
Large diff (26 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e2_accuracy.tex +9 −0
Large diff (10 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e2_runtime.tex +9 −0
Large diff (10 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e3_fits.tex +10 −0
Large diff (11 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e4.tex +10 −0
Large diff (11 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e5.tex +16 −0
Large diff (17 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e6.tex +11 −0
Large diff (12 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_e7.tex +17 −0
Large diff (18 lines) is not loaded by default to keep the page fast.Load diff
added paper/tables/tab_primitives.tex +75 −0
Large diff (76 lines) is not loaded by default to keep the page fast.Load diff
modified src/estimators/realized.cpp +13 −7
Large diff (40 lines) is not loaded by default to keep the page fast.Load diff
Menu

Theme