Repository navigation
Run the cleanup model and the Windows engine on processors without AVX2 - #62
Merged
Merged
Conversation
llama.cpp in the cleanup runtime was built with ggml's default x86 options, which need AVX2, FMA, F16C and BMI2. On older processors the runtime stopped with SIGILL at the first load (#37). x86_64 packages now ship three builds (sayso-cleanup, sayso-cleanup-avx, sayso-cleanup-baseline), and the client starts the best one that the processor runs. A runtime that still stops on an illegal instruction is reported as a processor that cannot run the local model, with a clear message in Settings. The Linux engine builds parakeet.cpp's ggml CPU backend for plain x86-64 for the same reason. scripts/test-cleanup-cpus.sh runs each build under QEMU on the oldest processor it is for. Fixes #37
whisper-rs-sys leaves GGML_NATIVE on, so MSVC built whisper.cpp for the CPU of the CI runner, and the Windows engine stopped with an illegal instruction on processors without AVX2 (issue #37), the same problem as the cleanup runtime. - bundle-windows.ps1 builds the engine three times with GGML_NATIVE=OFF: sayso-engine.exe (AVX2, FMA, F16C, BMI2), sayso-engine-avx.exe and sayso-engine-baseline.exe, signs them, and package-engine.ps1 ships all three in the engine zip. The installer quits all three on uninstall. - The CPU detection of the cleanup client moves to sayso_core::cpu, and the engine client uses it to start the best engine build in the app folder. - When a model stops the engine with an illegal instruction, the engine client marks it Failed with the new reason unsupported_cpu, answers its later requests without the engine, and does not load it again after the restart, so the engine does not crash in a loop. - sayso-engine-sdk's find_engine picks the best build in a Windows release folder, with its own copy of the check.
Resolve the conflicts with the static sayso-bridge build (bundle-linux.sh, releasing.md) and the new fake engine files, and apply the linux.yml change from the description of #62.
whisper-rs-sys does not run its build script again when a GGML_* variable changes, so the AVX2 engine in target could keep a whisper.cpp built before with GGML_NATIVE on, from a cargo build or the CI cache (issue #37).
The QEMU 6.2 of Ubuntu 22.04 does not emulate AVX or AVX2, so the AVX2 build stopped on Haswell and the AVX build failed to load on SandyBridge. A job on Ubuntu 24.04 (QEMU 8.2) runs the builds of the tarball, and a failure there no longer keeps the packages from being uploaded.
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.
What changes
Before: the local cleanup model crashed on any x86_64 processor without AVX2 (#37). llama.cpp in
sayso-cleanupis built withGGML_NATIVE=OFF, and ggml then turns on AVX, AVX2, FMA, F16C and BMI2 by default, so the runtime died with SIGILL at the first load and Settings showed only "signal 4".After: x86_64 packages ship three builds of the cleanup runtime,
sayso-cleanup(AVX2, FMA, F16C, BMI2),sayso-cleanup-avx(AVX, SSE 4.2) andsayso-cleanup-baseline(plain x86-64), and the app starts the best one this processor runs. If a runtime still stops on an illegal instruction, Settings says the processor can't run the local model in this version and suggests updating or using a cloud provider.How:
crates/sayso-core/src/cpu.rsnames the builds and picks one withis_x86_feature_detected!(shared by the cleanup and engine clients).runtime.rsmaps SIGILL (signal 4 on Unix,0xC000001Don Windows) to a newRuntimeError::UnsupportedCpu, and refuses up front to start a known build this CPU can't run (unlessSAYSO_CLEANUP_PATHis set).scripts/build-cleanup.shbuilds the three variants withGGML_*=OFFenv vars, each in its own target dir.bundle-linux.shuses it;bundle-windows.ps1does the same for the three.exefiles. The deb/rpm, AUR, Nix, install.sh, Inno Setup uninstall and AppImage glibc check all takesayso-cleanup*.GGML_NATIVE=OFFtoo, so it had the same AVX2 default. Its CPU backend is now built for plain x86-64 (the models run on Vulkan, so the CPU side matters little for speed).scripts/test-cleanup-cpus.shruns each build underqemu-x86_64 -cpu(Haswell, SandyBridge, Nehalem, qemu64) on a tiny random GGUF fromscripts/tiny-gguf.py, and checks that the AVX2 build does stop on SandyBridge.cleanup_test_failed_cpu_detailin all 10 locales.Windows speech engine
Before: whisper-rs-sys leaves
GGML_NATIVEon, so MSVC built whisper.cpp insayso-engine.exefor the CI runner's CPU. The 0.13.0 exe uses AVX2, FMA and F16C instructions, so Whisper models on Windows probably crash the engine on a processor without AVX2, and the supervisor reloads the model after each restart.After: the Windows bundle has
sayso-engine.exe(AVX2, FMA, F16C, BMI2),sayso-engine-avx.exeandsayso-engine-baseline.exe, and the app starts the best one this processor runs. If a model still stops the engine on an illegal instruction, it shows as failed with a new reason, "The processor of this computer cannot run this model in this version of Sayso", and the engine isn't asked to load it again.How:
bundle-windows.ps1setsGGML_NATIVE=OFFand builds the engine three times, each in its own target dir, then copies and signs all three.package-engine.ps1puts all three in the engine zip, and the Inno Setup uninstaller quits all three.sayso-engine-clientpicks the build withsayso_core::cpu::best_in(unlessSAYSO_ENGINE_PATHis set). On an illegal-instruction exit it marks the model that was runningFailed { reason: UnsupportedCpu }, drops it from the models it reloads after a restart, and fails later requests for it without touching the engine.unsupported_cpu(set by the client, never sent by an engine) with its string in all 10 locales.sayso-engine-sdk'sfind_enginepicks the best build in a Windows release folder. It keeps its own copy of the CPU check, since the SDK may only depend onsayso-protocol.ud2) for a marked model, and a new test drives the whole crash, restart and fail-fast path.Fixes #37.
How you checked it
These ran on Linux x86_64 in a cloud container, not on a Mac.
cargo test -p sayso-cleanup-clientandcargo test -p sayso-i18n; the client CPU tests also underqemu-x86_64 -cpu SandyBridgeandqemu64cargo test -p sayso-engine-client(one test,vad_and_diarization_models_download_with_their_engine_object, fails here on the base commit too),cargo test -p sayso-core cpu::, thesayso-engine-sdklib tests and thesayso-appengine_text testscargo clippy -p sayso-core -p sayso-engine-client -p sayso-cleanup-client -p sayso-app -p sayso-engine-sdk --all-targets -- -D warningscargo check --target x86_64-pc-windows-gnuforsayso-core,sayso-engine-sdk,sayso-engine-clientandsayso-cleanup-clientscripts/check-deps.shReproduced #37 with the 0.13.0 release
sayso-cleanupunderqemu-x86_64 -cpu SandyBridge(hello works, load dies with signal 4), then built the three variants withscripts/build-cleanup.shand ranscripts/test-cleanup-cpus.shagainst them.For the Windows engine, I built whisper.cpp's ggml (the copy vendored in whisper-rs-sys 0.15.0) with the same three flag sets on Linux and ran F16, Q8_0, Q5_0 and Q4_K matrix products under QEMU: each build matched an f32 reference on the oldest CPU it's for, the AVX2 build died with SIGILL on SandyBridge and the AVX build on Nehalem. objdump shows no ymm in the baseline build and no FMA or F16C in the AVX build.
Not verified: no real pre-AVX2 hardware (QEMU only); the ggml check used GCC, not MSVC, so the MSVC flag mapping is untested until the Windows CI job;
sayso-enginecouldn't be built here (its native downloads are blocked in this container), so the parakeet.cpp change is untested until CI;bundle-windows.ps1,package-engine.ps1and the Inno Setup changes weren't run here. The Windows job now builds the engine three times, so it takes longer.Workflow change to add by hand
The push token can't change files under
.github/workflows, so this part isn't in the branch. It makes the Linux workflow check that everysayso-cleanup*build is installed and answers hello, and runsscripts/test-cleanup-cpus.shon x86_64. Apply it withgit applyon this branch..github/workflows/linux.yml
Generated by Claude Code