[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: How to build compatible packages that use Eigen?



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
> 



Reply to: