es-ude / es-ude/OnDeviceTraining
build: FP contraction diverges host vs MCU — decide global -ffp-contract policy
- Dominant language
- C
- Stars
- 1
- Forks
- 3
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 8
Description
## Verified finding (2026-07-13)
GCC **ignores** `#pragma STDC FP_CONTRACT` (long-standing, gcc PR 20785). Empirically verified against our toolchain: arm-none-eabi-gcc 10.3 at `-O2 -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16` emits `vfma.f32` for `acc + x[i]*y[i]` loops and `a + t*c` expressions **despite** the pragma at the top of the TU; `-ffp-contract=off` eliminates all fused ops (2 → 0 in the probe).
## Why this is invisible today — and why it bites at hardware bring-up
- x86-64 CI **cannot** contract: the baseline ISA has no FMA instruction without `-mfma`, so GCC's default `-ffp-contract=fast` has nothing to fuse. All host tests stay green.
- The `c-arm-cross-compile` job is compile-only — it never runs a test.
- Cortex-M4F/M7 have VFMA. Every MAC loop in the framework (Conv1d kernels, Matmul, Sum, the funnel epilogues, the upcoming PointwiseFused primitives) will round **differently on the MCU than on the host** under the default flags.
Consequence: the entire host-validated bit-trajectory story (bit-parity examples, gold suites, #300 sweeps) does **not** transfer to on-device runs. The divergence surfaces only when real hardware training is compared against host references — with no obvious cause.
## Decision needed (options)
1. **Global `-ffp-contract=off`** for all framework libs (and the arm toolchain file): determinism host==MCU, measurable slowdown on M4F/M7 (every MAC pays separate mul+add).
2. **Documented divergence**: keep `fast` on ARM for speed, declare host↔MCU bit-parity out of scope (float-twin = sanity, not gate — consistent with the memory-over-accuracy vision, but weakens every future on-device debugging session).
3. **Per-lib policy**: `off` where rounding order is a documented contract (PointwiseFused does this already — see the PR-B plan), `fast` for throughput-critical kernels, with the divergence stated in docs/conventions.
Option 3 is the pragmatic start; the real decision point is first hardware bring-up.
## Precedent
The PR-B plan (`PointwiseFused`) already binds `target_compile_options( PRIVATE -ffp-contract=off)` per-lib and demotes the pragma to documentation/Clang-backup — that is the template for whichever scope is chosen.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Contributor guide
Research direction
Start by reading the PR-B PointwiseFused plan and the ARM toolchain file, then review the existing c-arm-cross-compile job and its FP contraction probe. Compare the three proposed scopes; done means the project has a chosen -ffp-contract policy, matching build settings, and documented host-versus-MCU rounding expectations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cmake
- Domain
- build-system, embedded-iot, performance
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100