Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: Allow exporting Eigen3 alignment values #4098

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

stephenswat
Copy link
Member

@stephenswat stephenswat commented Feb 18, 2025

As I discovered in #4049, having Eigen3 types on ABI boundaries invites a variety of compiler issues. In cases where ACTS and the depending project are compiled with different vectorization instruction sets, the ABIs become incompatible with each other, because the matrices are differently aligned.

This commit adds the ACTS_ENFORCE_EIGEN3_ALIGNMENT flag which, if enabled, will encode the Eigen3 alignment in the ACTS shared object, and the ACTS find_package code will then attempt to read this and set it appropriately on any dependent targets.

Closes #4049.

Summary by CodeRabbit

  • New Features

    • Introduced a new build configuration option to enforce Eigen3 memory alignment during compilation.
    • Enhanced the build process with error handling and warnings related to Eigen3 alignment settings.
    • Added a new source file to support Eigen3 alignment functionality.
  • Documentation

    • Updated the getting-started guide to include details on the new alignment enforcement option.

Copy link

coderabbitai bot commented Feb 18, 2025

Walkthrough

Integrated into the build process, new configurations are. A CMake option, ACTS_ENFORCE_EIGEN3_ALIGNMENT, introduced to control Eigen3 alignment settings is. Associated modifications include adding a source file for alignment information, updating target source listings, and adjusting the configuration script to enforce alignment requirements. Updated, the documentation has been to reflect these changes.

Changes

File(s) Change Summary
CMakeLists.txt, docs/getting_started.md Added new CMake option ACTS_ENFORCE_EIGEN3_ALIGNMENT (default OFF) to control public Eigen3 compiler definitions for alignment.
Core/src/Utilities/CMakeLists.txt
Core/src/Utilities/Eigen3Alignment.cpp
Added new source file Eigen3Alignment.cpp to the ActsCore target which defines a constant with Eigen3 alignment information.
cmake/ActsConfig.cmake.in Added a conditional block that, if ACTS_ENFORCE_EIGEN3_ALIGNMENT is enabled, verifies the ActsCore target, extracts alignment values from the object file, and sets the compile definition EIGEN_MAX_ALIGN_BYTES.
Core/CMakeLists.txt New custom command added to verify Eigen3 alignment information in the ActsCore library post-build.

Suggested labels

automerge

Suggested reviewers

  • paulgessinger

Poem

Aligned, the code now is, hmm!
New options bloom, in force they persist.
Eigen3 whispers its secrets in bytes,
CMake weaves paths of order and light.
May progress guide you, as the force ignites!
Yes, build strong your projects shall be.

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added this to the next milestone Feb 18, 2025
@github-actions github-actions bot added Component - Core Affects the Core module Infrastructure Changes to build tools, continous integration, ... Component - Documentation Affects the documentation labels Feb 18, 2025
@stephenswat stephenswat force-pushed the build/public_eigen3_alignment branch from f829e04 to 3d70e96 Compare February 18, 2025 12:08
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
cmake/ActsConfig.cmake.in (1)

120-146: Use generator expressions instead of deprecated LOCATION property, you should.

Hmmm. Reading the object file, a fragile approach it is. Preferred, a generator expression $<TARGET_FILE:ActsCore> might be, to locate the compiled artifact across various build configurations. In multi-config environments, break this code could, yes.

A potential revision:

-  get_target_property(_ACTS_CORE_LOCATION ActsCore LOCATION)
+  set(_ACTS_CORE_LOCATION "$<TARGET_FILE:ActsCore>")

Then adapt your file-reading logic accordingly, you must, hmm?

CMakeLists.txt (1)

131-132: Option naming consistent, it is.

Good addition, the new alignment option is. Possibly wish you may to expand its documentation or usage examples for clarity, ensure new builders do.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b9bf31 and f829e04.

📒 Files selected for processing (5)
  • CMakeLists.txt (1 hunks)
  • Core/src/Utilities/CMakeLists.txt (1 hunks)
  • Core/src/Utilities/Eigen3Alignment.cpp (1 hunks)
  • cmake/ActsConfig.cmake.in (1 hunks)
  • docs/getting_started.md (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • Core/src/Utilities/CMakeLists.txt
  • Core/src/Utilities/Eigen3Alignment.cpp
⏰ Context from checks skipped due to timeout of 90000ms (20)
  • GitHub Check: CI Bridge / lcg_106a: [alma9, gcc14]
  • GitHub Check: CI Bridge / lcg_106a: [alma9, gcc13]
  • GitHub Check: CI Bridge / build_gnn_tensorrt
  • GitHub Check: CI Bridge / lcg_105: [alma9, clang16]
  • GitHub Check: CI Bridge / lcg_105: [alma9, gcc13]
  • GitHub Check: CI Bridge / build_linux_ubuntu
  • GitHub Check: CI Bridge / linux_ubuntu_2204_clang
  • GitHub Check: CI Bridge / linux_ubuntu_2204
  • GitHub Check: unused_files
  • GitHub Check: linux_ubuntu_extra (ubuntu2204, 20, clang++)
  • GitHub Check: CI Bridge / build_exatrkx
  • GitHub Check: linux_ubuntu_extra (ubuntu2204, 20, g++)
  • GitHub Check: CI Bridge / build_exatrkx_cpu
  • GitHub Check: CI Bridge / clang_tidy
  • GitHub Check: CI Bridge / build_exatrkx_cpu
  • GitHub Check: CI Bridge / clang_tidy
  • GitHub Check: missing_includes
  • GitHub Check: macos
  • GitHub Check: build_debug
  • GitHub Check: linux_ubuntu
🔇 Additional comments (1)
docs/getting_started.md (1)

319-319: Documentation aligned with new option, it is.

Clear and consistent, hmm. The mention of ACTS_ENFORCE_EIGEN3_ALIGNMENT in the build options section is good. Enough, it appears. Approved, this is.

@stephenswat stephenswat force-pushed the build/public_eigen3_alignment branch from 3d70e96 to e27cb0e Compare February 18, 2025 12:35
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d70e96 and e27cb0e.

📒 Files selected for processing (5)
  • CMakeLists.txt (1 hunks)
  • Core/src/Utilities/CMakeLists.txt (1 hunks)
  • Core/src/Utilities/Eigen3Alignment.cpp (1 hunks)
  • cmake/ActsConfig.cmake.in (1 hunks)
  • docs/getting_started.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • Core/src/Utilities/CMakeLists.txt
  • docs/getting_started.md
  • CMakeLists.txt
  • Core/src/Utilities/Eigen3Alignment.cpp
🔇 Additional comments (2)
cmake/ActsConfig.cmake.in (2)

121-124: Wise validation of prerequisites, this is!

Clear and necessary, the target validation is. Prevent configuration failures early, it does.


135-145:

❓ Verification inconclusive

Hmm, process the alignment value wisely, you do.

Proper handling of edge cases and clear messaging, I sense. Yet verify the alignment value's impact on dependent projects, we must.

Run this script to check alignment value propagation:


🏁 Script executed:

#!/bin/bash
# Description: Verify alignment value propagation to dependent targets

# Test: Check if the compile definition is properly propagated
cmake --build . --target help | grep ActsCore
cmake --trace-expand --find-package=Acts . 2>&1 | grep -A 5 "Setting ACTS Eigen3 alignment"

Length of output: 232


Manual verification required, it is.

The code handles edge cases and messaging well, yes. However, the test script failed to run due to missing cmake (command not found), making the propagation of the compile definition into dependent projects uncertain. I advise you to run the verification script in an environment where cmake is available, or manually check that the ActsCore target correctly receives the -DEIGEN_MAX_ALIGN_BYTES definition.

  • Ensure cmake is properly installed and in your PATH.
  • Re-run tests to confirm that "Setting ACTS Eigen3 alignment" is printed and the value correctly propagates.
  • Check the target_compile_definitions(ActsCore ...) usage when building dependent targets.

Comment on lines +126 to +133
set(_ACTS_CORE_EIGEN3_ALIGNMENT_REGEX "ACTS::EigenAlignment=([0-9]+)")
get_target_property(_ACTS_CORE_LOCATION ActsCore LOCATION)

file(
STRINGS ${_ACTS_CORE_LOCATION} _ACTS_CORE_EIGEN3_ALIGNMENT_VALUE_STRING
LIMIT_COUNT 1
REGEX ${_ACTS_CORE_EIGEN3_ALIGNMENT_REGEX}
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Handle the case of missing target location, we must.

Missing, the error handling for target location property is. If get_target_property fails, undefined behavior we may face.

Apply this change, you should:

 get_target_property(_ACTS_CORE_LOCATION ActsCore LOCATION)
+if (NOT _ACTS_CORE_LOCATION)
+  message(FATAL_ERROR "Failed to get ActsCore target location.")
+endif()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
set(_ACTS_CORE_EIGEN3_ALIGNMENT_REGEX "ACTS::EigenAlignment=([0-9]+)")
get_target_property(_ACTS_CORE_LOCATION ActsCore LOCATION)
file(
STRINGS ${_ACTS_CORE_LOCATION} _ACTS_CORE_EIGEN3_ALIGNMENT_VALUE_STRING
LIMIT_COUNT 1
REGEX ${_ACTS_CORE_EIGEN3_ALIGNMENT_REGEX}
)
set(_ACTS_CORE_EIGEN3_ALIGNMENT_REGEX "ACTS::EigenAlignment=([0-9]+)")
get_target_property(_ACTS_CORE_LOCATION ActsCore LOCATION)
if (NOT _ACTS_CORE_LOCATION)
message(FATAL_ERROR "Failed to get ActsCore target location.")
endif()
file(
STRINGS ${_ACTS_CORE_LOCATION} _ACTS_CORE_EIGEN3_ALIGNMENT_VALUE_STRING
LIMIT_COUNT 1
REGEX ${_ACTS_CORE_EIGEN3_ALIGNMENT_REGEX}
)

Copy link

github-actions bot commented Feb 18, 2025

📊: Physics performance monitoring for e917b5a

Full contents

physmon summary

As I discovered in acts-project#4049, having Eigen3 types on ABI boundaries invites
a variety of compiler issues. In cases where ACTS and the depending
project are compiled with different vectorization instruction sets, the
ABIs become incompatible with each other, because the matrices are
differently aligned.

This commit adds the `ACTS_ENFORCE_EIGEN3_ALIGNMENT` flag which, if
enabled, will encode the Eigen3 alignment in the ACTS shared object, and
the ACTS `find_package` code will then attempt to read this and set it
appropriately on any dependent targets.

Closes acts-project#4049.
@stephenswat stephenswat force-pushed the build/public_eigen3_alignment branch from e27cb0e to e917b5a Compare February 18, 2025 15:12
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
Core/CMakeLists.txt (1)

89-91: Regular expression, more strict it should be.

The pattern [[:digit:]]{4}, any four digits it matches. More specific format for alignment value, enforce we should.

Improve pattern to match exact format:

-        \"ACTS::EigenAlignment=[[:digit:]]{4}\" ||
+        \"ACTS::EigenAlignment=[0-9][0-9][0-9][0-9]$\" ||
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e27cb0e and e917b5a.

📒 Files selected for processing (6)
  • CMakeLists.txt (1 hunks)
  • Core/CMakeLists.txt (1 hunks)
  • Core/src/Utilities/CMakeLists.txt (1 hunks)
  • Core/src/Utilities/Eigen3Alignment.cpp (1 hunks)
  • cmake/ActsConfig.cmake.in (1 hunks)
  • docs/getting_started.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • Core/src/Utilities/CMakeLists.txt
  • docs/getting_started.md
  • cmake/ActsConfig.cmake.in
  • CMakeLists.txt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: merge-sentinel

@andiwand
Copy link
Contributor

Thinking about this a bit more I believe this is the best solution. I wondered if it would also make more sense to have a CMake flag to set the alignment explicitly from outside which would be a bit more direct but requires manual intervention.

I have a few more questions

  1. Eigen has no mechanism for this? This seems like a standard problem no? Potentially they would ask you to compile all projects with the same settings?
  2. Does the include / linking order matter on the client side if users include/link Eigen and ACTS separately?
  3. Why do we guard this with ACTS_ENFORCE_EIGEN3_ALIGNMENT? It seems like this is always beneficial no?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is compiled into ACTS so we can later extract it from the binary right?

Wouldn't it be easier to put it in a text file and install it along ACTS and then read it from the text file to enforce the compiler flag?

@paulgessinger
Copy link
Member

paulgessinger commented Feb 19, 2025

Does the include / linking order matter on the client side if users include/link Eigen and ACTS separately?

This is actually an important point: in Athena we require the Athena-based Eigen headers to be included before ours, because they add their plugins. Not all packages link against ActsCore on the Athena side, do we introduce ABI incompatibilities between packages that use ACTS ones that don't?

I suspect we do, and if I'm correct, we cannot do it this way or at least we can't turn it on on Athena.

@andiwand
Copy link
Contributor

Potentially we could have a target which just introduces this definition so we do not risk incompatibilities with other clients? Something like ActsEigenDefinitions

@stephenswat
Copy link
Member Author

  1. Eigen has no mechanism for this? This seems like a standard problem no? Potentially they would ask you to compile all projects with the same settings?

As far as I know, no, there is no standard mechanism for this. The common wisdom is not to expose Eigen types on your ABI boundary at all, but I think this ship has failed. Rightfully, nobody saw this monumental ass-pain coming. Anyway, there is a way to enforce universal Eigen code, namely to either 1) set EIGEN_MAX_ALIGN_BYTES to zero which disables all alignment requirement, or by 2) specifying Eigen::NoAlign on the matrix type. The problem is that this has potentially severe performance downsides.

  1. Does the include / linking order matter on the client side if users include/link Eigen and ACTS separately?

I don't think so; Eigen is header-only so it does not have any objects of its own, and any object using both Eigen and ACTS would get the EIGEN_MAX_ALIGN_BYTES flag on the command line. Because it comes from the command line, include order should not matter.

That being said, there is another pathological case here, namely if we have library A and B, where A depends on B, A depends on Acts, and B depends on Eigen, and A and B use Eigen3 types over their ABI boundary. Because then B will not inherit the Eigen flag from Acts, while A does. I didn't think of that. 😢

  1. Why do we guard this with ACTS_ENFORCE_EIGEN3_ALIGNMENT? It seems like this is always beneficial no?

The problem is that providing the same -D flag with different values is a compiler warning or error, so if a project insists on adding their own value, it would be nice to be able to support that.

@stephenswat
Copy link
Member Author

This is actually an important point: in Athena we require the Athena-based Eigen headers to be included before ours, because they add their plugins. Not all packages link against ActsCore on the Athena side, do we introduce ABI incompatibilities between packages that use ACTS ones that don't?

Not a header include issue, but as I wrote above I do think this is (unfortunately) an issue with dependent libraries...

@andiwand
Copy link
Contributor

That being said, there is another pathological case here, namely if we have library A and B, where A depends on B, A depends on Acts, and B depends on Eigen, and A and B use Eigen3 types over their ABI boundary. Because then B will not inherit the Eigen flag from Acts, while A does. I didn't think of that. 😢

But that we can never treat right? It is annoying but I would not worry too much about it. If we ever encounter it we have to either compile with consistent flags or somehow tweak the alignment for both libraries to be the same.

@paulgessinger
Copy link
Member

@andiwand But if this setup here doesn't avoid that problem, I don't necessarily think we should add this to the CMake config to begin with.

@stephenswat
Copy link
Member Author

Yeah I think we need to rethink this... And unfortunately I don't think there is any good (=easy and foolproof) solution to this problem.

@andiwand
Copy link
Contributor

We discussed this in the morning and there are two options

  1. We let Eigen autodetect the alignment as we do now but then we should add some kind of mechanism to let the user detect the alignment used during compilation so they can set the same alignment on their side to make the ABI compatible
  2. We add options to the CMake to allow the user specifying the alignment used by Eigen. This way the user can orchestrate their build to be consistent without discovering what ACTS used/detected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component - Core Affects the Core module Component - Documentation Affects the documentation Infrastructure Changes to build tools, continous integration, ...
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use of Eigen causes segmentation faults in digitization reader
3 participants