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>
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