I'm aware of the alignment issue arising when using Eigen's types in conjunction with dynamic memory. Thus, I've decided to disable vectorization with Eigen::DontAlign
in accord with this page, yet the following code still raises SIGSEGVs consistently on execution. I'd be very happy if someone could shed some light upon why this happens. From my point of view, using Eigen::DontAlign
should have gotten me rid of alignment intricacies.
#include <Eigen/Dense>
#include <vector>
int main()
{
using vec_t = Eigen::Matrix< double, 4, 1, Eigen::DontAlign >;
std::vector< vec_t > foo;
foo.emplace_back( 0.0, 0.0, 0.0, 1.0 );
vec_t vec{ -4.0, 1.0, 3.0, 1.0 };
foo.push_back( vec );
}
GDB Output:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000408bed in Eigen::internal::evaluator<Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 2, 4, 1> > >::packet<0, double __vector(4)>(long long, long long) const (this=0x22fa90, row=0, col=0)
at C:/Dev/Eigen/Eigen/src/Core/CoreEvaluators.h:197
197 return ploadt<PacketType, LoadMode>(m_data + row + col * m_outerStride.value());
(gdb) l
192 PacketType packet(Index row, Index col) const
193 {
194 if (IsRowMajor)
195 return ploadt<PacketType, LoadMode>(m_data + row * m_outerStride.value() + col);
196 else
197 return ploadt<PacketType, LoadMode>(m_data + row + col * m_outerStride.value());
198 }
199
200 template<int LoadMode, typename PacketType>
201 EIGEN_STRONG_INLINE
(gdb) bt
#0 0x0000000000408bed in Eigen::internal::evaluator<Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 2, 4, 1> > >::packet<0, double __vector(4)>(long long, long long) const (this=0x22fa90, row=0, col=0) at C:/Dev/Eigen/Eigen/src/Core/CoreEvaluators.h:197
#1 0x000000000040678a in Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::assign_op<double, double>, 0>::assignPacket<0, 0, double __vector(4)>(long long, long long) (this=0x22fa60, row=0, col=0) at C:/Dev/Eigen/Eigen/src/Core/AssignEvaluator.h:652
#2 0x0000000000406863 in Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::assign_op<double, double>, 0>::assignPacketByOuterInner<0, 0, double __vector(4)>(long long, long long) (this=0x22fa60, outer=0, inner=0) at C:/Dev/Eigen/Eigen/src/Core/AssignEvaluator.h:666
#3 0x00000000004068e0 in Eigen::internal::copy_using_evaluator_innervec_CompleteUnrolling<Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::assign_op<double, double>, 0>, 0, 4>::run (kernel=...) at C:/Dev/Eigen/Eigen/src/Core/AssignEvaluator.h:274
#4 0x00000000004064d5 in Eigen::internal::dense_assignment_loop<Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::evaluator<Eigen::Matrix<double, 4, 1, 2, 4, 1> >, Eigen::internal::assign_op<double, double>, 0>, 2, 2>::run (kernel=...) at C:/Dev/Eigen/Eigen/src/Core/AssignEvaluator.h:468
#5 0x0000000000406693 in Eigen::internal::call_dense_assignment_loop<Eigen::Matrix<double, 4, 1, 2, 4, 1>, Eigen::Matrix<double, 4, 1, 2, 4, 1>, Eigen::internal::assign_op<double, double> > (dst=..., src=..., func=...) at C:/Dev/Eigen/Eigen/src/Core/AssignEvaluator.h:724
#6 0x00000000004062ab in Eigen::internal::Assignment<Eigen::Matrix<double, 4, 1, 2, 4, 1>, Eigen::Matrix<double, 4, 1, 2, 4, 1>, Eigen::internal::assign_op<double, double>, Eigen::internal::Dense2Dense, void>::run (dst=..., src=..., func=...) at C:/Dev/Eigen/Eigen/src/Core/AssignEvaluator.h:862
#7 0x00000000004065a3 in Eigen::internal::call_assignment_no_alias<Eigen::Matrix<double, 4, 1, 2, 4, 1>, Eigen::Matrix<double, 4, 1, 2, 4, 1>, Eigen::internal::assign_op<double, double> > (dst=..., src=..., func=...) at C:/Dev/Eigen/Eigen/src/Core/AssignEvaluator.h:819
#8 0x0000000000405bdc in Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 2, 4, 1> >::_set_noalias<Eigen::Matrix<double, 4, 1, 2, 4, 1> > (this=0x3c2680, other=...) at C:/Dev/Eigen/Eigen/src/Core/PlainObjectBase.h:728
#9 0x0000000000406070 in Eigen::Matrix<double, 4, 1, 2, 4, 1>::Matrix(Eigen::Matrix<double, 4, 1, 2, 4, 1>&&) (this=0x3c2680, other=<unknown type in F:\GitHub\Radon\bin\Radon.exe, CU 0x0, DIE 0x1faef>) at C:/Dev/Eigen/Eigen/src/Core/Matrix.h:278
#10 0x000000000040c666 in std::_Construct<Eigen::Matrix<double, 4, 1, 2, 4, 1>, Eigen::Matrix<double, 4, 1, 2, 4, 1> >(Eigen::Matrix<double, 4, 1, 2, 4, 1>*, Eigen::Matrix<double, 4, 1, 2, 4, 1>&&) (__p=0x3c2680, __args#0=<unknown type in F:\GitHub\Radon\bin\Radon.exe, CU 0x0, DIE 0x1faef>) at C:/Dev/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/stl_construct.h:75
#11 0x000000000040ad69 in std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<Eigen::Matrix<double, 4, 1, 2, 4, 1>*>, Eigen::Matrix<double, 4, 1, 2, 4, 1>*> (__first=..., __last=..., __result=0x3c2680) at C:/Dev/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/stl_uninitialized.h:75
#12 0x000000000040c8bf in std::uninitialized_copy<std::move_iterator<Eigen::Matrix<double, 4, 1, 2, 4, 1>*>, Eigen::Matrix<double, 4, 1, 2, 4, 1>*> (__first=..., __last=..., __result=0x3c2680) at C:/Dev/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/stl_uninitialized.h:126
#13 0x000000000040c9ff in std::__uninitialized_copy_a<std::move_iterator<Eigen::Matrix<double, 4, 1, 2, 4, 1>*>, Eigen::Matrix<double, 4, 1, 2, 4, 1>*, Eigen::Matrix<double, 4, 1, 2, 4, 1> > (__first=..., __last=..., __result=0x3c2680) at C:/Dev/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/stl_uninitialized.h:281
#14 0x000000000040ccaf in std::__uninitialized_move_if_noexcept_a<Eigen::Matrix<double, 4, 1, 2, 4, 1>*, Eigen::Matrix<double, 4, 1, 2, 4, 1>*, std::allocator<Eigen::Matrix<double, 4, 1, 2, 4, 1> > > (__first=0x3c2980, __last=0x3c29a0, __result=0x3c2680, __alloc=...) at C:/Dev/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/stl_uninitialized.h:304
#15 0x000000000040b648 in std::vector<Eigen::Matrix<double, 4, 1, 2, 4, 1>, std::allocator<Eigen::Matrix<double, 4, 1, 2, 4, 1> > >::_M_emplace_back_aux<Eigen::Matrix<double, 4, 1, 2, 4, 1> const&> (this=0x22fde0, __args#0=...) at C:/Dev/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/vector.tcc:420
#16 0x000000000040ba16 in std::vector<Eigen::Matrix<double, 4, 1, 2, 4, 1>, std::allocator<Eigen::Matrix<double, 4, 1, 2, 4, 1> > >::push_back (this=0x22fde0, __x=...) at C:/Dev/mingw-w64/x86_64-6.3.0-posix-seh-rt_v5-rev1/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/stl_vector.h:924
#17 0x000000000040167f in main () at F:\GitHub\Radon\Radon.cxx:10
(gdb)
Environment: Windows 7 64-bit SP1
Hardware: i7-6800k (AVX2 support)
Compiler: MinGW-w64 (x86_64-6.3.0-posix-seh-rt_v5-rev1
)
Flags -Wall -Wextra -pedantic-errors -Wno-deprecated -std=c++14 -march=native -g -ggdb -fno-omit-frame-pointer
Eigen version: 3.3.2
I don't have a solution per se, but more insight as to what happened. First off, I can reproduce with gcc 5.3.0 on MinGW as well, so it's not just you. Second of all, by running gcc -march=native -Q --help=target ... | grep enabled
I obtained a list of the the flags enabled by -march=native
on my (different) setup (I'm using an older i5, etc.). I divided those in a binary fashion until I came up with the list of two flags (in my case) needed to trigger the same error in a modified version of your MCVE (+1):
#include <Eigen/Core>
#include <Eigen/StdVector>
#include <iostream>
#include <vector>
using vec_t = Eigen::Matrix< double, 4, 1, Eigen::DontAlign >;
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(vec_t)
int main()
{
// , Eigen::aligned_allocator<vec_t>
std::vector< vec_t> foo;
std::cout << "Before emplace_back\n";
foo.emplace_back( 0.0, 0.0, 0.0, 1.0 );
std::cout << "Before vec\n";
vec_t vec{ -4.0, 1.0, 3.0, 1.0 };
std::cout << "Before push_back\n";
foo.push_back( vec );
std::cout << "After push_back\n";
return 0;
}
They were -mavx
and -mf16c
, two flags that enable AVX instructions. The gdb output is slightly different, as I did use the instructions here:
Program received signal SIGSEGV, Segmentation fault. 0x0000000000403ca4 in Eigen::internal::ploadu(Eigen::internal::unpacket_traits::type const*) ( from=0x312340) at C:/include/Eigen3.3.2/Eigen/src/Core/arch/AVX/PacketMath.h:218 218 template<> EIGEN_STRONG_INLINE Packet4d ploadu(const double* from) { EIGEN_DEBUG_UNALIGNED_LOAD return _mm256_loadu_pd(from); }
So we see that Eigen is still vectorizing with AVX using unaligned loads, as we only told Eigen not to align and we didn't specify -DEIGEN_DONT_VECTORIZE
in the preprocessor (or as a #define
before including Eigen). Adding that removes the segfault. So, the workaround is to disable vectorization (even unaligned). If that's enough, great. If not, wait for ggael & co. (or someone else) to figure out a better solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With