Skip to content

ecfinality: Python reference test only runs on FMA3-capable CPUs #142

Description

@Reiers

Context: TestCalcValidatorProb_PythonReference in chain/ecfinality/calculator_test.go compares Go's reorg-probability calculations against reference values generated with scipy/numpy. The reference values were calibrated on a modern x86_64 CPU with FMA3 (fused multiply-add) enabled.

Problem: CPUs without FMA3 (Ivy Bridge / older, e.g. E5-16xx v2) produce results that drift by ~2e-5 relative at the deep-depth values (e.g. 4.627122e-12 vs 4.627232e-12 at depth=30), because math.Log and math.Pow use a different reduction order without the fma intrinsic. Those values are already close to float64 noise floor, but the current 1e-12 tolerance can't distinguish 'algorithm regression' from 'CPU FP behavior' at that scale.

Current workaround (2026-07-23, this issue's parent PR #141): t.Skip() on non-FMA x86_64. Preserves the tight 1e-12 tolerance on CPUs that can meet it, without loosening the check globally. Surfaced during the CI move to self-hosted runners on the Reiers home cluster (node1 = E5-1650v2, Ivy Bridge).

Proper long-term fix (pick one):

  1. Per-CPU-class reference vectors. Generate a second set of reference values on a non-FMA CPU using the same scipy invocation; ship both, dispatch by cpu.X86.HasFMA. Keeps 1e-12 parity on every hardware target we care about.

  2. FMA-locked implementation. Force the Go math to use / not use FMA consistently across CPUs (e.g. via math.FMA explicitly in CalcValidatorProb, or via a build tag + software fallback). Makes results deterministic across CPU generations at the cost of some throughput on modern chips.

  3. Interval arithmetic. Store reference values as [lo, hi] intervals and check containment. Cleanest but requires reworking the reference generator.

Priority: low. Structural tests still exercise the algorithm on every CPU. The Python parity check remains active on modern CPUs (which is where the algorithm is actually run in production).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions