{
  "project": "fast-mnist-nn",
  "sha": "f8efce910ad687ddb7e758dae1bcc21681edcce1",
  "baselineName": "Own single-thread scalar baseline (OpenMP off, -march=native off)",
  "conditions": {
    "n": "square matrices (dot/transpose/axpy at listed sizes); 784-30-10 MLP for learn/classify",
    "machine": "Shrees-MacBook.local, 8 CPUs, release build",
    "compiler": "Apple clang 17.0.0; configs: baseline (scalar), native (-march=native), openmp+native"
  },
  "series": [
    {
      "workload": "benchDot/256 (openmp+native vs scalar baseline)",
      "subject_value": 1379830,
      "baseline_value": 4835360,
      "ratio": 0.285363,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchDot/128 (openmp+native vs scalar baseline)",
      "subject_value": 374400,
      "baseline_value": 575281,
      "ratio": 0.650813,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchTranspose/1024 (openmp+native vs scalar baseline)",
      "subject_value": 502426,
      "baseline_value": 978383,
      "ratio": 0.513527,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchTranspose/512 (openmp+native vs scalar baseline)",
      "subject_value": 87913.6,
      "baseline_value": 198735,
      "ratio": 0.442365,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchAxpy/1024 (openmp+native vs scalar baseline)",
      "subject_value": 114910,
      "baseline_value": 230626,
      "ratio": 0.49825,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchAxpy/512 (openmp+native vs scalar baseline)",
      "subject_value": 35845.5,
      "baseline_value": 55847.8,
      "ratio": 0.641843,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchAxpy/128 (openmp+native vs scalar baseline)",
      "subject_value": 23916.7,
      "baseline_value": 3486.03,
      "ratio": 6.86073,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchTranspose/128 (openmp+native vs scalar baseline)",
      "subject_value": 23661.8,
      "baseline_value": 5440.86,
      "ratio": 4.3489,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchDot/64 (openmp+native vs scalar baseline)",
      "subject_value": 89130.1,
      "baseline_value": 65252.1,
      "ratio": 1.36594,
      "unit": "ns/op",
      "lowerIsBetter": true
    },
    {
      "workload": "benchLearn throughput (openmp+native vs baseline)",
      "subject_value": 48636.1,
      "baseline_value": 48755.4,
      "ratio": 0.997553,
      "unit": "img/s",
      "lowerIsBetter": false
    },
    {
      "workload": "benchClassify throughput (openmp+native vs baseline)",
      "subject_value": 69993.9,
      "baseline_value": 81627.6,
      "ratio": 0.857479,
      "unit": "img/s",
      "lowerIsBetter": false
    }
  ],
  "notes": "ratio = openmp+native / scalar baseline. For ns/op (lowerIsBetter), <1 is a win. Big matrices win: benchDot/256 0.285x (~3.5x faster), transpose/1024 0.514x (~1.95x), axpy/1024 0.498x (~2x). Small ops lose to OpenMP overhead — the honest negative result: axpy/128 6.86x SLOWER, transpose/128 4.35x slower, dot/64 1.37x slower — which is exactly why OpenMP is gated behind size thresholds. learn throughput is flat across configs (0.998x) because the NN hot paths are intentionally serial SIMD, not OpenMP-parallelized; classify dips ~14% (0.857x) under openmp+native (OpenMP thread overhead on already-serial paths, kept honest rather than dropped). MNIST accuracy is computed at runtime by the CLI but never committed, so it is not included."
}
