Live data from Hacker News

Eigen: A C++ template library for linear algebra

eigen.tuxfamily.org

81–85 of 85 posts

Re: Eigen: A C++ template library for linear algebra

#81
For anyone still reading this: I'm now confused by Eigen reportedly being basically on a par with optimized L3 BLAS, which I assume doesn't just mean punting to optimized BLAS, which it seems it can do. I can't see any indication that you can do run-time dispatch on the micro-architecture, which I think is important; I saw very poor results until I examined CMakeLists.txt. Anyway, I cmade v3.4 with -DEIGEN_TEST_AVX512DQ=on, which seems most appropriate for my SKX system, and then did make blas. I ran my normal initial quick test using the OpenBLAS 0.3.15 dgemm benchmark, which reports a plateau of ~99000 MFlops. LD_PRELOADing libeigen_blas.so with the same binary under the same conditions (bound to a core, with the hpc-compute tuned profile) gave ~66000 MFlops.

What did I do wrong?

Re: Eigen: A C++ template library for linear algebra

#82
post #80

Earlier quoted context omitted.

In my case Eigen is handling some 3000x3000 and bigger matrices. For these scenarios, it’s performance is about 98% of BLAS libraries, which is more than enough when combined with the ease and practicality of Eigen. It also handles RAM placement, so it doesn’t get affected by memory fragmentation. Their current performance page is here [0]. [0]: https://eigen.tuxfamily.org/index.php?title=Performance_moni...

[0] still looks bad for complex (CGEMM, I assume). It doesn't have comparisons there, but Eigen's claim to be faster than any free BLAS is surely wrong. (I wouldn't doubt its similar if it has the right loop structure and prefetching, and a few percent is within the normal variance of HPC runs anyway, so not worth worry about.) Unfortunately it isn't convenient for me, not being clever enough for C++, but I've nothin…

I can't comment for performance of Eigen concerning complex calculations, since my work lives in the real domain.

On the other hand, Eigen didn't claim to be faster than any BLAS during my interaction with informational side of their website. Nowadays, I just get the latest version, update my code and directly reach for their reference guide.

However, being used by both CERN (in LHC ATLAS) and TensorFlow, I guess they're no slouch in terms of performance (it also genuinely amazed my heavy BLAS fan professor at my Jury when the performance numbers came up). Another plus is, Eigen's ability to be used in CUDA kernels (though I didn't try it yet).

On the other hand, they're insanely fast (almost BLAS fast in my experience) for what I'm doing, and it's really well optimized (shows when you use -O3, especially on the solvers side). Also, it has neat capabilities like dynamic matrices and instant submatrix access (you can get a submatrix of a matrix, or just patch in a submatrix in a single call).

About RAM placement: From my experience, code becomes overly dependent on non-fragmented memory when allocating big matrices and/or vectors naively (i.e. in a contiguous manner), and execution fails as the node you're running on (or your computer) gets busier with other code. Eigen counters this by intelligently dividing bigger matrices into smaller chunks, both optimizing the access time and reducing (or effectively eliminating from my experience) the risk of segmentation faults related to failed memory allocations due to not having not enough undivided space in the memory space.

Re: Eigen: A C++ template library for linear algebra

#83
post #80

Earlier quoted context omitted.

[0] still looks bad for complex (CGEMM, I assume). It doesn't have comparisons there, but Eigen's claim to be faster than any free BLAS is surely wrong. (I wouldn't doubt its similar if it has the right loop structure and prefetching, and a few percent is within the normal variance of HPC runs anyway, so not worth worry about.) Unfortunately it isn't convenient for me, not being clever enough for C++, but I've nothin…

I can't comment for performance of Eigen concerning complex calculations, since my work lives in the real domain. On the other hand, Eigen didn't claim to be faster than any BLAS during my interaction with informational side of their website. Nowadays, I just get the latest version, update my code and directly reach for their reference guide. However, being used by both CERN (in LHC ATLAS) and TensorFlow, I guess the…

> On the other hand, Eigen didn't claim to be faster than any BLAS during my interaction with informational side of their website.

It claims to be faster than any free BLAS in the FAQ (but talks about ATLAS and GotoBLAS there). Given how close GotoBLAS in the guise of OpenBLAS gets to peak performance for GEMM, that would be dubious without measuring 2/3 of OB DGEMM performance. I assume claims of speed are for when BLAS is actually providing it. (I'm too experienced to be susceptible to appeals to authority of HEP software!)

Thanks for explaining the memory thing. I'd hope HPC code wouldn't be subject to SEGVs due to memory allocation failing (for two reasons), but you typically want arrays on the stack and otherwise large pages to minimize TLB misses (per Goto).

I'm not intending to bash Eigen, happy if people can use performant free software.

Re: Eigen: A C++ template library for linear algebra

#84
post #73

Eigen is the standard choice (for good reason!) for many linear algebra projects, especially in robotics, but there is a big downside users should be aware of before they chose it. Eigen makes extensive use of expression templates in C++ to collapse complex operation sequences into streamlined and minimal calculations. This is generally ok, until you need a debug build. I've regularly seen debug builds of software us…

You can create custom build configurations to set the optimizations and add debug info. Or just add instrumentation code (print debugging) which is more useful for debugging heavy numerical stuff most of the time anyway. Running anything through valgrind or cachegrind will have several orders of magnitude slowdown - that's inherent to how the tools work. To your last point, just add -g to your compile flags and see h…

I don't think you quite understand the problem. The problem wasn't turning on optimizations or getting debug info, the problem was getting Eigen-based linear algebra code to run at a sufficiently reasonable speed when optimizations were disabled because doing so would make other surrounding logic easier to debug (or you needed to run some analysis tool like Valgrind on a debug build).

For example, we had simulation test suites which would run ~30 seconds of real-world time. If we can run those sims at 10x real time, each only takes 3 seconds, great! But with optimizations turned off, heavy Eigen code would run 1000x slower, which means the sims now take nearly 3000 seconds to run when bug hunting in the non-Eigen related surrounding logic. This already makes the test suite virtually un-runnable in debug builds, but if you want to then run those binaries through Valgrind (which tacks on another 100-1000x performance tax) you're now talking about something which is completely intractable. You can't run optimized builds through Valgrind without potentially introducing false positives, so you can't even run Valgrind on only the optimized builds... you just can't run it at all because your linear algebra library is slowing everything down.

The core problem is Eigen's heavy use of expression templates, which the optimizer cuts through just fine. But without the optimizer turned on, it adds layers and layers and layers of unnecessary abstraction. Because these are all templates, C++ expands all this code at every call site, making it substantially less efficient and impossible to shim out by linking with an optimized build of Eigen itself.

The only approach I've seen get close to making this work was an attempt by an engineer to use explicit template instantiation to create a separate binary with all the necessary Eigen functions which could be compiled separately with the optimizer turned on. However, this proved too nightmarish because since Eigen can template on the dimensions of everything, you need to know up front exactly all the various instantiations of Eigen types the program uses. This might be doable by writing a clang plugin or something, but doing it by hand was just way too much work because the codebase was huge, so we couldn't justify spending more time on it.

Re: Eigen: A C++ template library for linear algebra

#85

Earlier quoted context omitted.

One has shape (N, 1) and one has shape (N). Always having a trailing 1 is a pain in many settings. Matlab has that “trailing 1” all the time and it’s a PITA.

Why do you say it's a pain? After working with numpy for the last two years, that's the part I miss most about matlab.

There are many reasons the "-by-1" doesn't make sense.

* If a vector is an n-by-1 array (a "matrix"), why not an n-by-1-by-1-by-1-by-1?

* What is a row vector in something like a function space? Is sin(t) a row or column vector?

* You _can_ think of a matrix as acting "to the right (on a column vector)" and "to the left (on a row vector)", but this disrupts the notion of a matrix as a linear function acting on a thing (since it can act on two things). It's much more consistent to define a matrix acting on a vector, m(x), independent of "direction" and then define the transformations that let you go in the opposite direction (take the transpose of m which is a whole new matrix).

* Are physical quantities like velocity a row or column vector? Convention dictates they're column vectors, so in what scenario would it become a row vector? If I have a velocity, v1, that's a row vector and another, v2, that's a column vector, is it appropriate to calculate the projection of v1 onto v2? Should the projection operation be "aware" of the orientations? If all vectors are the same ("column vectors"), this isn't a problem -- you can always define the projection operation without special cases.

* In matlab specifically, if you have an n-by-1 array `a` and a 1-by-n array `b` with the same elements, then `a(i) == b(i)` but `a` and `b` are not the same thing.

Post reply on HN