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?
a = a.transpose()
, but they also mentioned that Eigen uses a run-time assertion to detect this and exits with a message. I guess that the problem is that as they state, In general, aliasing cannot be detected at compile time, and they favor efficiency. Performingb = a.transpose()
while creating a temporary would be quite inefficient – Manropea.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. – Fixeda.transposeInPlace()
exists as @Fixed said. Therefore,a = a.transpose()
could be discouraged anyway – Manropea = a.transpose()
should be detected easily. But all that are hypothesis. Only Eigen developers could provide a real answer – Manropea.transposeInPlace()
exists, and thata = a.transpose()
is incorrect. I know it is possible to write correct code in Eigen. My question is whether there is rationale behind the apparent inconsistency in their interface design. – Humminga = a.transpose()
: This is in fact done at runtime (unless assertions are disabled), but detecting this at compile-time is generally not possible (just consider the case where you pass two matrices by reference, which could but don't have to be the same). Also, what is hard to detect (even at runtime) is aliasing between sub-blocks of matrices. – Fixed