Repository navigation
Conversation
A pull_request run builds only the Windows and Linux CPU jobs; the GPU and macOS builds and create-release skip it, so a PR never publishes a release or spends GPU build hours. The workflow token is read-only by default, and only create-release gets contents: write. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
GGML_NATIVE=OFF turns on AVX2, FMA, F16C and BMI2 for every CPU build, so the static whisper-server dies at startup with STATUS_ILLEGAL_INSTRUCTION or SIGILL on Intel processors before Haswell and on AMD FX (OpenWhispr/openwhispr#2356). Build two more CPU-only whisper-servers per Windows and Linux x64, at upstream ggml's ivybridge (SSE4.2 + AVX + F16C) and sandybridge (SSE4.2 + AVX) levels, and publish them as four new release assets. MSVC has no F16C switch without AVX2, so the Windows ivybridge build defines __F16C__, which only ggml-cpu reads. Each job checks the exact CMake CPU line of all three builds; the existing builds and assets are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
verify-cpu-levels runs each whisper-server build for processors without AVX2 on an emulator of exactly its level (Intel SDE on Windows, QEMU user mode on Ubuntu 24.04) the way OpenWhispr starts it: a real model, Silero VAD, and samples/jfk.wav through /inference, then checks the build's own system_info. It also checks the next build up is stopped at startup on that processor, which proves the emulator enforces the level and that a build dies before serving (what OpenWhispr's fallback relies on), and starts each build beside llama.cpp's libraries as in OpenWhispr's resources/bin. Every download is pinned by sha256. create-release waits for it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The first emulated run showed the ivybridge whisper-server starting and serving on a Sandy Bridge processor, which lacks F16C: ggml builds its fp16 tables with scalar code and first runs F16C in the transcription kernels. A build that only faults mid-transcription defeats OpenWhispr's fallback, which moves to the next older build when whisper-server dies at startup. examples/server/cpu-level-check.cpp compares the instruction sets ggml's CPU code was built for (ggml_cpu_has_avx/f16c/fma/avx2/bmi2) with CPUID and XGETBV before main(). On a mismatch it names what is missing and raises the same illegal-instruction fault the processor would (ud2). It is opt-in (OPENWHISPR_CPU_LEVEL_CHECK) and enabled for the ivybridge and sandybridge builds only: a hypervisor or translator can hide features it still executes (Rosetta 2 does), and the existing builds must behave exactly as before. verify-cpu-levels now also accepts the illegal-instruction exit such a refusal produces under SDE, and requires the ivybridge build's refusal on Sandy Bridge to come from its level check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
From the review of the first two runs: - Every PR to master runs the CPU builds and verify-cpu-levels, not only PRs that touch the workflow: the level check and ggml live elsewhere. A newer push cancels a PR's running check. - Each result prints as its check finishes, and an error inside a check (the server dying mid-request, a failed download) is a FAIL line instead of a traceback that hides every result. Downloads retry into a .part file. Timeouts match what the runners take, well inside the job's limit. - The primary must be stopped by the emulator itself (SDE's chip check), and a level build's refusal must name exactly the missing set, so a stray illegal-instruction exit no longer passes. - New checks: the primary is stopped on a Piledriver-class AMD FX (AVX, F16C, FMA, no AVX2 or BMI2) under QEMU, since that rests on one BMI2 instruction in ggml's startup code; the sandybridge build refuses a processor without AVX. - The server is reached without a proxy, and "ready" requires the process it started to be alive; system_info is checked for every extension above SSE4.2. - The docstring now says what each check proves, and the release notes no longer promise Haswell-era Pentium and Celeron models the AVX2 builds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- A download that never matches its sha256 raises an ordinary error, so the check it belongs to prints a FAIL line instead of ending the run; no sleep after the last attempt. - Note that the Piledriver check leans on a QEMU quirk (SHLX gated on BMI1, which its model lacks), and when that would stop matching real hardware. - Release notes: Intel Pentium, Celeron and Atom models without AVX include most made before 2021-2023, not only before 2020. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In short: every x64 CPU
whisper-serverwe publish needs AVX2, so it crashes on startup on older PCs (Intel before 2013's Haswell, AMD FX). This adds two builds for those processors, a startup check so each refuses to run on a processor below its level, and a CI check that runs each one on an emulated processor of exactly that generation. OpenWhispr then falls back to them (OpenWhispr/openwhispr#2396). Refs OpenWhispr/openwhispr#2356, also reported in OpenWhispr/openwhispr#1418, OpenWhispr/openwhispr#1613 and OpenWhispr/openwhispr#793.Problem
-DGGML_NATIVE=OFFdoes not mean "baseline". When not cross-compiling, ggml turns every x86 option up to AVX2 on (ggml/CMakeLists.txt:141-158). The 0.0.10 CI logs print exactly that:The server is statically linked, so nothing picks a CPU variant at run time. On a processor with AVX but no AVX2, FMA or BMI2, it dies in
ggml_cpu_init()before it serves anything:STATUS_ILLEGAL_INSTRUCTION, exit code 3221225501.OpenWhispr/openwhispr#1613's Event Viewer fault offset
0xc072ddisassembles to a BMI2shlx eax,edx,eaxinsideggml_cpu_initin the shipped exe. The same instruction sits at the same offset in 0.0.8 and 0.0.10.The
ggml-cpu-ivybridge.dllthat reporters found in OpenWhispr'sresources/binbelongs to llama-server's llama.cpp bundle. whisper-server imports no ggml DLL.Change
whisper-serverbuilds per Windows and Linux x64, at upstream ggml's own levels:ivybridge: SSE4.2 + AVX + F16C. Covers Intel Ivy Bridge and AMD Piledriver/Steamroller/Jaguar, which includes every processor named in the reports.sandybridge: SSE4.2 + AVX. Covers Intel Sandy Bridge and AMD Bulldozer.whisper-server-{win32,linux}-x64-cpu-{ivybridge,sandybridge}.zip. The Windows zips carry the same MSVC runtime DLLs as the existing CPU zip.__F16C__, and MSVC compiles ggml's F16C intrinsics under/arch:AVX. Onlyggml/src/ggml-cpureads that macro.examples/server/cpu-level-check.cpp, opt-in with-DOPENWHISPR_CPU_LEVEL_CHECK=ON):main()it compares what ggml's CPU code was built for (ggml_cpu_has_avx/f16c/fma/avx2/bmi2) with CPUID and XGETBV. On a mismatch it prints e.g.whisper-server: built for F16C, which this processor does not supportand raisesud2, the same illegal-instruction fault the processor would.Adding CPU backend variantline of all three builds. The primary lines must stay exactly as today. The Windows job also checks the ivybridge cache for/D__F16C__in both C and C++ flags.Why two levels, not one: without F16C, ggml converts every fp16 weight one element at a time through a lookup table, and Whisper's models are fp16. In local x86_64 runs of jfk.wav (Rosetta, loaded host, so ratios only), the sandybridge build was about 7× slower than ivybridge. ivybridge was close to the AVX2 build.
CI
verify-cpu-levels(new, matrix win32/linux) runs.github/scripts/verify-cpu-levels.py. It uses Intel SDE-ivb/-snbon Windows and QEMU user mode-cpu IvyBridge/SandyBridgeon Ubuntu 24.04; 22.04's QEMU 6.2 cannot emulate AVX. Per platform it checks:ggml-tiny.bin, Silero VAD, the app's arguments), transcribessamples/jfk.wavvia/inference, and itssystem_inforeports exactly its level.resources/bin, becauseggml_backend_load_all()loads them.petarpetrovt/setup-sdeGitHub mirror. No third-party action code runs, and its sha256 independently matches the one oven-sh/bun pins for the same Intel file.verify-cpu-levels. Nothing proved PR build: bundle MSVC runtime DLLs into win32 zips #6 before it merged, for example.create-releaseare skipped.contents: readby default. Onlycreate-releasegetscontents: write, and it now also waits forverify-cpu-levels.Evidence
Configure lines on real MSVC 19.44 and GCC 11.4. The primary lines are identical to 0.0.10:
First run (36502940851, before the level check). 5 of 6 checks passed per platform. Check 4 failed on both:
whisper-server-*-cpu-ivybridge on sandybridge started serving. That failure is why the level check exists.Run 36504535683 (level check): all 12 checks pass.
Run 36509459145 (hardened script, with the AMD FX-class and no-AVX checks): all 15 checks pass.
Local (Rosetta) check of the level-check build:
built for AVX/built for F16C.ROSETTA_ADVERTISE_AVX=1, it runs normally.Not verified here
Release
Merging this does not publish anything. 0.0.11 is a manual
workflow_dispatchon master.verify-cpu-levelsmust pass beforecreate-releaseruns.🤖 Generated with Claude Code