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 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
>