2017-02-11 30 views
4

Я знаю проблему выравнивания, возникающую при использовании типов Eigen в сочетании с динамической памятью. Таким образом, я решил отключить векторизацию с Eigen::DontAlignin accord with this page, но следующий код по-прежнему вызывает SIGSEGVs последовательно при выполнении. Я был бы очень рад, если бы кто-то мог пролить свет на то, почему это происходит. С моей точки зрения, использование Eigen::DontAlign должно было избавить меня от сложных тонкостей.SIGSEGV с использованием Eigen и std :: vector

#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 Выход:

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) 

Окружающая среда: Windows 7 64-разрядные SP1

Оборудование: i7-6800k (поддержка AVX2)

Компилятор: MinGW-w64 (x86_64-6.3.0-posix-seh-rt_v5-rev1)

Флаги -Wall -Wextra -pedantic-errors -Wno-deprecated -std=c++14 -march=native -g -ggdb -fno-omit-frame-pointer

Эйген версия: 3.3.2

+0

Разве вы не смотрите на http://eigen.tuxfamily.org/dox/group__TopicStlContainers.html, раздел «Случай std :: vector»? – oLen

+0

@oLen Я думаю, что совет относится только к выровненному корпусу; почему еще я должен быть вынужден использовать выравнивающий распределитель для неуравновешенных классов? Во всяком случае, я пошел вперед и попробовал это, чтобы быть уверенным, но, к сожалению, это все еще SIGSEGVd. – Fytch

ответ

2

У меня нет решения по себе, но больше понимания относительно того, что случилось. Во-первых, я могу воспроизвести с gcc 5.3.0 на MinGW, так что это не только вы. Во-вторых, запустив gcc -march=native -Q --help=target ... | grep enabled, я получил список флагов, включенных -march=native на моей (другой) установке (я использую более старый i5 и т. Д.). Я разделил тех, в двоичной моде, пока я не пришел со списком из двух флагов (в моем случае), необходимый для запуска и ту же ошибки в модифицированную версии вашего 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; 
} 

Они были -mavx и -mf16c, два флага, которые позволяют выполнять инструкции AVX. Выход gdb немного отличается, так как я использовал инструкции here:

Программный сигнал SIGSEGV, ошибка сегментации. 0x0000000000403ca4 in Eigen :: internal :: ploadu (Eigen :: internal :: unpacket_traits :: type const *) ( from = 0x312340) в 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); }

Итак, мы видим, что Эйген еще векторизации с AVX использования нелинейных нагрузок, как мы говорили только Эйгену не выравнивать и мы не указуем -DEIGEN_DONT_VECTORIZE в препроцессора (или как #define перед включением Эйгена). Добавление, которое удаляет segfault. Таким образом, обходной путь заключается в отключении векторизации (даже без выравнивания). Если этого достаточно, отлично. Если нет, ждите ggael & co. (или кто-то другой), чтобы найти лучшее решение.

+0

Компиляция с '-DEIGEN_DONT_VECTORIZE', кажется, разрешает проблему временно, спасибо. Тем не менее, я бы очень хотел воспользоваться SIMD. Документация Eigen позволяет предположить, что он поддерживает SIMD в неизмененных данных путем хранения/загрузки из соответствующих регистров при необходимости (при указании «Eigen :: DontAlign»).Поэтому у меня все еще создается впечатление, что это ошибка в Eigen, как в коде, так и в документации. – Fytch

+0

Отсюда мой комментарий о ожидании ggael & co. (Разработчики Eigen). –