Skip to content

fix: graceful AVX2 CPU check with clear error message instead of crash#2083

Open
Gosha250311 wants to merge 3 commits intonexus-xyz:mainfrom
Gosha250311:fix/floating-point-avx2-check
Open

fix: graceful AVX2 CPU check with clear error message instead of crash#2083
Gosha250311 wants to merge 3 commits intonexus-xyz:mainfrom
Gosha250311:fix/floating-point-avx2-check

Conversation

@Gosha250311
Copy link

Problem

Closes #2060

On CPUs that do not support AVX2 instructions (Intel pre-Haswell,
AMD pre-Ryzen), the CLI crashes immediately with a cryptic
Floating point exception (core dumped) instead of a helpful error.

This happens because the CLI is compiled with -C target-cpu=native
which bakes in AVX2 instructions at compile time. When these
instructions execute on unsupported hardware, the OS sends SIGILL
which appears as a floating point exception.

Fix

Added a CPU feature check at the very start of main() before any
prover code runs. If AVX2 is not available, the CLI exits gracefully
with a clear, actionable error message.

The check is skipped entirely on non-x86_64 platforms (ARM, etc.)
since they use NEON/scalar paths with no AVX2 dependency.

Error message shown to users

Architecture

Refactored into 3 composable functions for testability:

  • avx2_missing_message() - error text, testable independently
  • cpu_feature_error(bool) - logic, injectable for unit tests
  • check_cpu_features() - real hardware detection

Testing

79 tests pass, 0 failures, 0 warnings
11 new tests added covering message content, logic injection,
and platform-specific behaviour

Георгий Николаев and others added 3 commits March 6, 2026 18:34
…y clamp

Two bugs prevented --max-threads from taking effect:

1. Memory clamping fired automatically whenever --max-threads was set
   (condition was `max_threads.is_some() || check_mem`). On machines
   with ≤8 GB RAM the formula `floor(RAM * 0.75 / 4 GB)` evaluates to 1,
   silently overriding the user's value and causing the dashboard to always
   show "Threads: 1". The guard is now gated on --check-memory only.

2. The Rayon thread pool (used by nexus-sdk's Stwo prover inside each
   proving subprocess) was never configured from num_workers. Added a
   --num-threads flag to the hidden prove-fib-subprocess subcommand;
   prove_and_validate forwards the value when spawning the subprocess,
   and prove_fib_subprocess calls rayon::ThreadPoolBuilder::build_global
   at startup so the prover uses exactly the requested thread count.

Also adds unit tests for the num_workers computation logic and integration
tests confirming both --max-threads and --num-threads are accepted by clap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On older CPUs that lack AVX2 instructions, the prover crashes with a
floating point exception (SIGILL) deep in the proving stack with no
useful message. This check runs at the very start of main(), before any
other initialization, and exits with a clear human-readable error
explaining which CPU generations are supported.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Problem
-------
The Nexus CLI is compiled with `-C target-cpu=native` (.cargo/config.toml),
which bakes AVX2 instructions into the binary at compile time via the
stwo-prover SIMD backend.  When the resulting binary is run on a CPU that
lacks AVX2 (pre-2013 Intel / pre-2017 AMD), the OS delivers SIGILL, which
Rust surfaces as a "floating point exception" with no actionable guidance.

Solution
--------
Check for AVX2 at the very start of `main()`, before the panic hook and
before any other initialisation, so we can exit with a clear message instead
of crashing.

Implementation details
----------------------
The check is factored into three small, composable functions to keep the
logic fully testable without needing hardware that lacks AVX2:

  avx2_missing_message()          — the human-readable error text (static str)
  cpu_feature_error(avx2: bool)   — maps a bool to Option<&'static str>;
                                    accepts an injected value so unit tests
                                    can exercise both branches on any machine
  check_cpu_features()            — calls is_x86_feature_detected!("avx2")
                                    on x86_64; returns None on all other arches

Both helper functions are gated with #[cfg(any(target_arch = "x86_64", test))]
so they compile on non-x86_64 during `cargo test` (for unit tests) but are
absent in non-test non-x86_64 release builds.

Other CPU features investigated
--------------------------------
stwo-prover also has an avx512f code path, but that is an optional
enhancement selected at compile time via target_feature; AVX2 is the
mandatory baseline on x86_64.  No other ISA extensions (SSE4, BMI, …) are
required independently because they are all implied by AVX2.

Tests added (src/main.rs — cpu_check_tests)
--------------------------------------------
  avx2_error_message_names_avx2
  avx2_error_message_names_intel_and_amd
  avx2_error_message_names_specific_cpu_generations   (Haswell/2013, Ryzen/Zen/2017)
  avx2_error_message_explains_the_cpu_is_too_old
  cpu_feature_error_returns_none_when_avx2_present    (injectable: avx2=true)
  cpu_feature_error_returns_message_when_avx2_absent  (injectable: avx2=false)
  cpu_check_passes_on_avx2_capable_x86_64             (#[cfg(target_arch="x86_64")])
  cpu_check_is_skipped_on_non_x86_64                  (#[cfg(not(target_arch="x86_64"))])

Tests added (tests/cli.rs — integration)
-----------------------------------------
  avx2_check_does_not_trigger_on_supported_x86_64_hardware
  avx2_check_absent_on_non_x86_64
  cli_exits_zero_for_help_on_supported_hardware

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

Error: Floating point exception (core dumped) when trying to run CLI

1 participant