Skip to content

perf: determinism-neutral speedups + opt-in inference pipelining (and docs/tests)#3

Merged
BenjaminDEMAILLE merged 6 commits into
IPNP-BIPN:apple-silicon-native-v2-prfrom
nh13:nh_dv-2-perf
Jun 24, 2026
Merged

perf: determinism-neutral speedups + opt-in inference pipelining (and docs/tests)#3
BenjaminDEMAILLE merged 6 commits into
IPNP-BIPN:apple-silicon-native-v2-prfrom
nh13:nh_dv-2-perf

Conversation

@nh13

@nh13 nh13 commented Jun 22, 2026

Copy link
Copy Markdown

Stacked on #2 — review after it merges, when this diff reduces to its unique commits. Default runtime behavior is unchanged (both new paths are opt-in, default off). Build green; ctest all pass.

Performance (default behavior unchanged)

  • -mcpu=apple-m1 (ISA/scheduling only; fast-math stays off, so the deterministic conv/BNNS reductions remain bit-identical — guarded by the determinism microtests), plus std::move/reserve/flag-hoisting in make_examples, TFRecord reader buffering, a string_view WriteRecord overload, and removal of a dead/divergent SIMD header.
  • Opt-in --enable_inference_pipelining (default off): overlaps the GPU MPSGraph backbone of batch N+1 with the CPU BNNS finalize + CVO build of batch N, via a single FIFO finalize worker and a 2-slot double buffer. Validated on chr20 (HG002, 4731 examples): record set, metadata, and order are byte-identical to serial, and the genotype-probability differences equal the default metal backend's own run-to-run nondeterminism envelope (serial-vs-serial == serial-vs-pipelined).

Docs / tests

  • Marked the stale Core ML ADR (docs/architecture.md) as superseded — the shipped backend is Metal MPSGraph FP32, coreml is debug-only, and the ANE is not engaged for the 7-channel input.
  • Corrected the conversion README inventory, added weight-conversion shape asserts, and fixed a stale test_savedmodel_reader assertion.

Self-review fixes folded in

  • emit_cvos now checks both ParseFromString return values instead of silently emitting a half-parsed record.
  • Added a WriterJoiner RAII guard so the async writer thread is joined on every early-return path (it previously hit std::terminate() on a joinable thread); ordered to destruct after the pipelined finalize worker so its queued records are still drained.

@BenjaminDEMAILLE

Copy link
Copy Markdown

Heads-up @nh13: I had to squash apple-silicon-native-v2-pr from 273 commits down to 1, because Google's CLA bot can't auto-scan PRs with more than 250 commits and this branch is the head of the upstream PR google#1085. The squash is content-identical (same tree hash 810ff855), only the history was flattened.

Side effect: this rewrote the base of your 4 open PRs (#3, #4, #6, #7), so they now show an inflated diff against r1.10. A rebase onto the new base fixes it cleanly (no real conflicts, the content is unchanged). The old base tip was 0cd41f859de445f5d8a60524b86b54bb418a043b, so:

git fetch origin
git rebase --onto origin/apple-silicon-native-v2-pr 0cd41f859de445f5d8a60524b86b54bb418a043b <your-branch>
git push --force-with-lease

Sorry for the churn, and thanks again for all the fixes. Your authorship is preserved via a Co-Authored-By trailer on the squashed commit.

nh13 added 6 commits June 24, 2026 11:16
- parity_check.autoload silently swallowed any decode error and switched
  formats via a bare except; fall back to the minimal decoder only on a
  raised error or zero rows, log which decoder is used, and print a
  shape-mismatch reason instead of indexing absent numeric keys.
- inception_v3_mil adds build-time shape asserts on the stem conv and the
  final linear so an HWIO->OIHW perm or dropped .T fails at convert time.
- bench._decode_feature asserts the decoded element count matches (h,w,c).
- test_savedmodel_reader asserted weights() raises NotImplementedError, but
  it is implemented now; assert it raises on a malformed bundle instead.
architecture.md's Phase-0 ADR named Core ML/MIL as the inference backend, but
the shipped default is Metal MPSGraph FP32 (call_variants_main.cc
--inference_backend=metal; coreml debug-only; ANE not engaged), matching
validation.md and scientific_report.md. Mark it SUPERSEDED and correct the
Decision, preserving the historical Phase-0 numbers. Fix the conversion README
(nonexistent requirements-metal.txt; coremltools>=9.0 TF-free) and the vendored
proto count (25->26, matching SOURCES.md).
Determinism-neutral CPU wins on the make_examples hot loop (output unchanged):
- std::move the read vector into working_reads on the no-realigner default
  path instead of deep-copying every Read proto (repointing the one later use).
- Hoist loop-invariant absl::GetFlag reads and the RealignerOptions proto to
  const locals computed once before the region loop.
- Emit a periodic 'processed X/Y regions' progress line.
- Attach a 1 MiB streambuf to the reader before open (the writer already
  coalesces into 1 MiB), cutting per-record read() syscalls. Pure buffering;
  format and decoded bytes unchanged.
- Add a WriteRecord(std::string_view) overload and pass the example payload
  by view from ExampleWriter::Add instead of materializing a std::string;
  on-disk framing is byte-identical.
- Add -mcpu=apple-m1 (ISA/scheduling only; fast-math stays off so the
  deterministic conv/bnns reductions remain bit-identical, guarded by the
  determinism microtests).
- Delete neon_base_color.h + its microtest: built-but-unused in production and
  semantically divergent from the live FillBaseColorBatch (a latent trap).
- Refresh the stale 'NOT YET WIRED' banner on neon_cigar_classify.h, which is
  in fact wired into allelecounter.cc.
Add --enable_inference_pipelining (default off) that overlaps the GPU
MPSGraph backbone of batch N+1 with the CPU BNNS finalize + CVO build of
batch N, for the two-stage Metal path only. A single finalize worker
drains a FIFO queue and is the sole CVO producer (shared emit_cvos
lambda), with a 2-slot double buffer (features/probs) and an
at-most-one-in-flight invariant, so output order is identical to the
serial path. Validated on chr20 (HG002, 4731 examples): record set,
metadata, and order are byte-identical to serial, and the genotype-prob
differences are exactly the default metal backend's own run-to-run
nondeterminism envelope (serial-vs-serial == serial-vs-pipelined).
@BenjaminDEMAILLE BenjaminDEMAILLE merged commit 6f03911 into IPNP-BIPN:apple-silicon-native-v2-pr Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants