available_parallelism() put ggml workers on Meteor Lake LP E-cores; every
per-node spin barrier then waits on the slowest worker while the rest burn
CPU: RTF ~22 at 14 threads vs 0.28 at 4 threads (~80x), same build. This
was the real W1 CPU-pathology root cause; /Od-vs-/O2 made no difference.
4 matches whisper.cpp upstream default and is the CPU-frugal choice
(NFR-RES-1). WA_WHISPER_THREADS env overrides for support/bench.
The cmake crate strips -O*/O* from CFLAGS and, with no explicit generator
on MSVC, overwrites CMAKE_C_FLAGS_RELEASE — so the previous CFLAGS=/O2
attempt could never work (verified: /DNDEBUG survived, /O2 stripped).
With CMAKE_GENERATOR=Ninja the override branch is skipped and CMake's
default Release flags (/O2 /Ob2 /DNDEBUG) reach ggml.
62 s real recording (48 kHz stereo, downmixed/resampled by the production
reader). Reference .txt is a placeholder; WER column is meaningless here,
only the hypothesis text counts.
cmake-rs hardcodes opt_level(0) and replaces CMake's Release C flags, so
ggml/whisper.cpp compiled at /Od — root cause of the W1 CPU-pathology
(RTF ~20) in docs/benchmarks/2026-07-parakeet-vs-whisper.md. cc-rs appends
env CFLAGS/CXXFLAGS last, restoring optimization for all native deps.
Merged-decoder (use_cache_branch/past_key_values) loop discovered from the
graph at load; step 1 runs the no-cache branch over the prompt, later steps
feed one token + cached KVs (decoder slots refreshed, encoder cross-attn KVs
kept from step 1). Decoder session lands on the Intel iGPU via the OpenVINO
GPU plugin (same staged runtime) with CPU-EP fallback and a
WA_ONNX_DECODER_DEVICE=cpu|gpu override; DirectML backends keep the CPU
decoder. Legacy decoder_model.onnx is removed once the merged graph loads.
Measured (Core Ultra 5 135U, base.en, 19s TTS clip, identical transcripts):
decoder on OpenVINO/GPU infer=1288ms vs CPU-EP infer=6098ms
Text row (confirm + full-width text + delete) over a wrapping meta row
(owner, due date, reminder). Also void the seekNonce dependency read to
satisfy no-unused-expressions.
- live diarization tick on split recordings now uses attribute_split (mic
channel = 'You' from the first pass) instead of whole-mix clustering +
voiceprint matching, which never reliably surfaced 'You' before stop
- attribute_split assigns via diarization::assign_split (channel-total
overlap) so the user's speech can't be swallowed by a longer far-side span
- stop_recording overlays live user renames over the automatic name map
- rename_speaker/map_speaker_to_participant rewrite notes.md's baked-in
**Name:** dialogue tags so the Notes pane follows the Speakers pane
- model_used records the ONNX model when the NPU/DirectML engine is routed
(was reporting the unused ggml model id) + info log naming the encoder EP