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 | std::shared_ptr<Backend> make_metal_backend(const PrecisionPolicy& policy) { | 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); | 240 | + static std::mutex m; static std::shared_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) | 241 | + if (cached) return cached->available() ? cached : nullptr; // one device/queue/library/pipeline cache/buffer pool per process | ||
| 242 | − auto p = std::make_shared<MetalBackend>(policy); cached = p; if (!p->available()) return nullptr; return p; | 242 | + cached = std::make_shared<MetalBackend>(policy); return cached->available() ? cached : nullptr; | ||
| 243 | } | 243 | } | ||
| 244 | 244 | ||||
| 245 | /// Fused realized accumulators when the backend is Metal (falls back to the four generic calls otherwise). | 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 | 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()}}; | 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 | 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; | 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 | // 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 | 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 | catch (const RaidError& ex) { row["error"] = ex.what(); row["converged"] = false; } rows[i] = row; } }); | 48 | catch (const RaidError& ex) { row["error"] = ex.what(); row["converged"] = false; } rows[i] = row; } }); | ||
| 49 | usize conv = 0; for (auto& r : rows) { conv += r.value("converged", false); r["kind"] = "fit"; r["experiment"] = "E3"; out << r.dump() << "\n"; } | 49 | usize conv = 0; for (auto& r : rows) { conv += r.value("converged", false); r["kind"] = "fit"; r["experiment"] = "E3"; out << r.dump() << "\n"; } | ||
| 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(); | 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 | struct RealizedOptions { | 25 | struct RealizedOptions { | ||
| 26 | bool bpv_finite_sample{true}; | 26 | bool bpv_finite_sample{true}; | ||
| 27 | bool fuse_kernels{true}; // Metal: one fused pass for all accumulators (ablation: false → 4 kernels) | 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 | bool annualize{false}; // multiply variances by `periods_per_year` | 29 | bool annualize{false}; // multiply variances by `periods_per_year` | ||
| 29 | f64 periods_per_year{252.0}; | 30 | f64 periods_per_year{252.0}; | ||
| 30 | ExecutionPlan plan{}; | 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