Skip to content

Bump Eigen submodule to 5.0.0 (closes #67)#264

Open
rhaist wants to merge 1 commit intosdatkinson:mainfrom
rhaist:experiment/eigen-5.0
Open

Bump Eigen submodule to 5.0.0 (closes #67)#264
rhaist wants to merge 1 commit intosdatkinson:mainfrom
rhaist:experiment/eigen-5.0

Conversation

@rhaist
Copy link
Copy Markdown

@rhaist rhaist commented May 3, 2026

Summary

Bumps Dependencies/eigen to the released Eigen 5.0.0 tag.

  • Submodule moves from 87300c93c (pre-3.5 dev snapshot, 2023-04-17) → 549bf8c75 (5.0.0, 2025-09-28).
  • One-line diff. No NAM source changes.

Why this closes #67

Issue #67 asks the project to follow Eigen's struct-having-Eigen-members guidance so consumers don't hit alignment crashes under aggressive vectorization, and so the README "Sharp edges" workarounds (EIGEN_MAX_ALIGN_BYTES=0, EIGEN_DONT_VECTORIZE) become unnecessary.

The Eigen 5.0 release notes resolve this at the library level. From CHANGELOG.md:

Eigen now uses the c++11 alignas keyword for static alignment. Users targeting C++17 only and recent compilers (e.g., GCC>=7, clang>=5, MSVC>=19.12) will thus be able to completely forget about all issues related to static alignment, including EIGEN_MAKE_ALIGNED_OPERATOR_NEW.

NAM already requires C++20 (CMakeLists.txt). With Eigen 5.0, no per-class macros, no aligned_allocator audit, and no EIGEN_MAX_ALIGN_BYTES overrides are needed for correct alignment of either fixed-size or dynamic-size Eigen members. The README "Sharp edges" section can be retired in a follow-up.

I also briefly explored an alternative PR adding EIGEN_MAKE_ALIGNED_OPERATOR_NEW to every class with Eigen members. Decided against it: today every member is dynamic-size (MatrixXf/VectorXf), so the macro is a runtime no-op, and Eigen 5.0 obsoletes it anyway. The submodule bump fixes the underlying problem rather than working around it.

What I tested locally

Platform: macOS (Darwin 25.4.0, AppleClang 21.0.0), C++20, Apple Silicon.

Reproduced the same matrix CI runs on Ubuntu (build.yml):

Variant Configure Compile run_tests benchmodel wavenet.nam benchmodel lstm.nam render
Debug, default GEMM clean clean, no new warnings Success 17.5 ms 10.1 ms OK
Debug, -DNAM_USE_INLINE_GEMM clean clean, no new warnings Success 9.5 ms 9.7 ms OK

The only warnings emitted in the new build are the three pre-existing -Wsign-compare warnings in Dependencies/AudioDSPTools/dsp/wav.cpp (unrelated, present on main).

Render bit-exactness check

I rendered example_models/wavenet.nam over example_audio/input.wav (96000 samples) on Eigen 3.4.90 (current main) and Eigen 5.0, with both GEMM paths, and compared SHA-256 hashes:

Variant SHA-256
Eigen 3.4.90, default GEMM 1d920928a7588f0455f8df088df3758d4f14e8afb4a3f09d5f9afdd477c533d9
Eigen 3.4.90, inline GEMM 465e0cb0c8be01f21aa570dce41fb754c0016abcf17dbfeac247fc195a9e84d1
Eigen 5.0.0, default GEMM be598b753d127d9c90e5cee8bb59235f16f3e5fd294c2cc2c6110968a6fc4470 ⚠️ different
Eigen 5.0.0, inline GEMM 465e0cb0c8be01f21aa570dce41fb754c0016abcf17dbfeac247fc195a9e84d1 ✅ identical

Inline GEMM is bit-exact across the bump (expected — that path bypasses Eigen's matrix product). Default Eigen GEMM is not bit-exact — Eigen 5.0 changes product evaluation/vectorization, producing different LSB rounding. run_tests still passes on both Eigen versions because the unit-test tolerances are wider than the rounding noise. Heads-up for the integration-tests workflow (Atkinson-Advanced-Modeling/NamIntegrationTests): if it pins golden audio bit-exactly against the current Eigen output, those goldens will need refreshing.

What I did NOT verify locally

I'm on macOS, so I could not exercise the Linux side of the existing CI matrix. Specifically not run locally:

  • build-ubuntu (libstdc++) — both default and NAM_USE_INLINE_GEMM
  • build-ubuntu-libcxx (libc++ via -DNAM_USE_LIBCXX_LINUX=ON) — both default and NAM_USE_INLINE_GEMM. This job exists specifically to cover the _LIBCPP_VERSION branch in wavenet/slimmable.h (atomic shared_ptr free-functions vs std::atomic<std::shared_ptr<…>>).
  • Windows / MSVC.

These will run on the existing .github/workflows/build.yml matrix when CI fires, which is the right place to catch any platform-specific Eigen 5 incompatibility.

Other Eigen 5.0 changes worth noting

From the changelog, the changes most relevant to NAM:

  • Eigen::aligned_allocator no longer inherits from std::allocator (C++ standard change). NAM does not use aligned_allocator directly — no impact.
  • C++14 minimum for Eigen 5.0 (NAM is C++20 — no impact).
  • New EIGEN_ALIGNOF(X) macro available if needed.
  • alignas-based static alignment as quoted above.

Suggested follow-ups (separate PRs, not in this one)

  1. Drop the README "Sharp edges" section now that the workaround it documents is no longer needed.
  2. Refresh integration-test goldens if any pin Eigen-3.x default-GEMM output bit-exactly.
  3. Consider whether Dependencies/AudioDSPTools/Dependencies/eigen (still pinned at a 3.4.90 dev snapshot from 2023-09-14, but unused by NAM core — only wav.cpp is compiled and it doesn't include Eigen) should be bumped in AudioDSPTools for consistency.

Test plan

  • CI: build-ubuntu (libstdc++, default GEMM) — green
  • CI: build-ubuntu (libstdc++, inline GEMM) — green
  • CI: build-ubuntu-libcxx (libc++, default GEMM) — green
  • CI: build-ubuntu-libcxx (libc++, inline GEMM) — green
  • CI: integration tests — green (or refreshed goldens if needed)
  • Local macOS, default GEMM: run_tests + benchmodel + render — all pass
  • Local macOS, NAM_USE_INLINE_GEMM: run_tests + benchmodel + render — all pass
  • Render hash comparison Eigen 3.4.90 vs 5.0 documented above

Updates Dependencies/eigen from a pre-3.5 dev snapshot
(87300c93c, 2023-04-17) to the released 5.0.0 tag (549bf8c75,
2025-09-28).

Why this closes sdatkinson#67
-------------------
Issue sdatkinson#67 asks that we follow Eigen's struct-having-Eigen-members
guidance to ensure correct alignment of Eigen members. The Eigen 5.0
release notes resolve this at the library level:

  > Eigen now uses the c++11 alignas keyword for static alignment.
  > Users targeting C++17 only and recent compilers (e.g., GCC>=7,
  > clang>=5, MSVC>=19.12) will thus be able to completely forget about
  > all issues related to static alignment, including
  > EIGEN_MAKE_ALIGNED_OPERATOR_NEW.

NAM already requires C++20 (see CMakeLists.txt). With Eigen 5.0, the
README "Sharp edges" workarounds (EIGEN_MAX_ALIGN_BYTES=0,
EIGEN_DONT_VECTORIZE) are no longer needed. A follow-up commit can
remove that section.

Refs sdatkinson#67.
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.

Ensure Eigen members are aligned correctly for optimized CPU instructions

1 participant