Don't know how to address this issue but have some relevant comments. Eigen library does not support run time dispatch for CPU ISAs. When a package is built upon the amd64 baseline ISA but ran on a modern CPU, the performance can be very poor. This is why I build the tensorflow and pytorch packages against libblas.so.3 (through update-alternatives). A good BLAS implementation is usually faster than the Eigen compiled in native ISA. For example, openblas.
Check if the library in question supports building against BLAS/LAPACK instead of Eigen. Good luck if the upstream does not support that. By the way, since there is no runtime ISA dispatch, the "-mavx" flag is likely a baseline violation with RC severity. I don't know whether Eigen implemented the dispatch in the latest version. But the current state of this library still seems to dispatch by preprocessor. On Wed, 2023-05-03 at 14:18 -0700, Dima Kogan wrote: > Hi. I'm packaging something that uses Eigen, and I'm running into a > persistent compatibility issue I don't currently know how to solve. Help > appreciated. > > Here's the problem. Eigen is a C++ header-only library that's heavy into > templating. So all the functions inside Eigen produce weak symbols, and > usually the linker will see many identical copies of the same weak > symbol, from each compile unit and shared object being linked. The > linker picks ONE of the weak definitions. This is the intended behavior > in C++ because every copy is supposed to be identical. But in Eigen > they're not identical: it does different things based on preprocessor > defines, and you get crashes. > > Here's a simplified illustration of what happens. > > > eigen3/Eigen/src/Core/util/Memory.h contains: > > EIGEN_DEVICE_FUNC inline void* aligned_malloc(std::size_t size) > { > check_that_malloc_is_allowed(); > > void *result; > #if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED > > EIGEN_USING_STD(malloc) > result = malloc(size); > > #if EIGEN_DEFAULT_ALIGN_BYTES==16 > eigen_assert((size<16 || (std::size_t(result)%16)==0) && "System's > malloc returned an unaligned pointer. Compile with > EIGEN_MALLOC_ALREADY_ALIGNED=0 to fallback to handmade aligned memory > allocator."); > #endif > #else > result = handmade_aligned_malloc(size); > #endif > > if(!result && size) > throw_std_bad_alloc(); > > return result; > } > > EIGEN_DEVICE_FUNC inline void aligned_free(void *ptr) > { > #if (EIGEN_DEFAULT_ALIGN_BYTES==0) || EIGEN_MALLOC_ALREADY_ALIGNED > > EIGEN_USING_STD(free) > free(ptr); > > #else > handmade_aligned_free(ptr); > #endif > } > > The EIGEN_DEFAULT_ALIGN_BYTES and EIGEN_MALLOC_ALREADY_ALIGNED macros > can vary based on things like __SSE__ and __AVX__ and such. > > Now let's say you're packaging a library. Let's call it libg2o. This is > NOT header-only, and somewhere it does #include <Eigen/....> which > eventually includes Memory.h. The libg2o.so that ends up in the > "libg2o0" package then gets a weak symbol for "aligned_malloc" and > "aligned_free" that encodes the compiler flags that were used when > building libg2o.so. > > So far so good. > > Now let's say you have a user. They're writing a program that uses both > libg2o and Eigen. They're writing their own application, not intended to > go into Debian. So they build with -msse -mavx and all the other fun > stuff. THEIR weak copies of "aligned_malloc" and "aligned_free" are > different and incompatible with the copies in libg2o. And the > application is then likely to crash because at least something somewhere > will be allocated with one copy and deallocated with another. > > This is just terrible design from the eigen and c++ people, but that's > what we have. Has anybody here run into this? How does one build the > libg2o package so that users don't crash their application when using > it? I tried to demand maximum alignment in libg2o, which fixes some > things but not all. Currently debugging to find a better solution, but I > suspect somebody has already fought this. > > Thanks >