Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Eigen make inconsistent default assumptions about aliasing?

Tags:

c++

eigen

eigen3

As a newcomer to Eigen there is something I am battling to come to terms with.

With matrix multiplication Eigen creates a temporary by default to avoid aliasing issues:

matA = matA * matA; // works fine (Eigen creates a temporary before assigning)

If it is safe to assume no aliasing, we can use .noalias() to allow for optimization:

matB = matA * matA; // sub-optimal (due to unnecessary temporary)
matB.noalias() = matA * matA; // more efficient

So Eigen here by default avoids making the unsafe assumption unless it is explicitly told that it is safe to assume no aliasing. So far so good.

However, for many other expressions, such as a = a.transpose() Eigen makes the unsafe assumption (that there are no aliasing issues) by default, and needs explicit intervention to avoid that unsafe assumption:

a = a.transpose().eval(); // or alternatively: a.transposeInPlace()

So if we are concerned about efficiency, it is not sufficient to be careful when there is potential aliasing, and it is not sufficient to be careful when there is no potential aliasing. We have to be careful both when there is potential aliasing, and when there is no potential aliasing, and decide whether a special intervention is warranted, based on whether the expression involves matrix multiplication or not. Is there some design rationale in Eigen for this "mixture of default expectations" in Eigen's interface?

like image 900
Museful Avatar asked Feb 28 '26 22:02

Museful


1 Answers

The comments present an answer to the question and are summarized here:

Eigen documentation mentioned effectively that you should not do that a = a.transpose(), but they also mentioned that Eigen uses a run-time assertion to detect this and exits with a message. The problem is that as they state, In general, aliasing cannot be detected at compile time, and they favor efficiency. Performing b = a.transpose() while creating a temporary would be quite inefficient.

Essentially it is a design choice. In general Eigen prefers efficiency, but matrix-products are a common source of accidental aliasing (and the extra copy usually is far less expensive than doing the product). For transpose better use a.transposeInPlace();. Most other expressions barely have aliasing issues, e.g., when adding two matrices you can only get problems if you access overlapping (but non-equal) memory regions.

The rationale is simply that products are much more expensive than temporary creation + O(n^2) copy. And yes, Eigen, just like any other BLAS library, use a O(n^3) matrix product algorithm. Theoretically more efficient algorithms payoff for huge products (n>3000 maybe even more), and more importantly, they yield to huge and unacceptable roundoff errors with floating point arithmetic (float/double).

This decision was made at the very early stage of Eigen developments, 10 years later I'd rather assume no aliasing unconditionally for consistency.

like image 83
2 revsMatt Avatar answered Mar 03 '26 12:03

2 revsMatt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!