New user self-registration is currently disabled. Please email eigen-core-team @ lists.tuxfamily.org if you need an account.
Bug 1389 - Unaligned assert with MSVC x64 and AVX
Unaligned assert with MSVC x64 and AVX
Status: RESOLVED FIXED
Product: Eigen
Classification: Unclassified
Component: Core - vectorization
3.3 (current stable)
x86 - 64-bit Windows
: Normal Crash
Assigned To: Nobody
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2017-02-03 11:46 UTC by Björn Piltz
Modified: 2017-02-03 16:07 UTC (History)
4 users (show)



Attachments
Compile with /arch:AVX (1.02 KB, text/plain)
2017-02-03 11:47 UTC, Björn Piltz
no flags Details

Description Björn Piltz 2017-02-03 11:46:17 UTC
The attached example either crashes or gives me the "unaligned assert" when I use /arch:AVX.

I'm using 3.3.1.

See https://bitbucket.org/bjornpiltz/eigen_msvc_avx_test/.
Comment 1 Björn Piltz 2017-02-03 11:47:40 UTC
Created attachment 771 [details]
Compile with /arch:AVX
Comment 2 Gael Guennebaud 2017-02-03 12:21:35 UTC
I cannot reproduce, but here is my guess: MSVC is not good at aligning the stack, so fix your Ray ctor from:

  Ray(const Mat34 P_, const Vec2& p_)

to

  Ray(const Mat34& P_, const Vec2& p_)
Comment 3 Björn Piltz 2017-02-03 12:26:27 UTC
Oh, I missed that. It doesn't help though. I'm using MSVC Community 2015 Update 3 
Here's the call stack:
>	AVX_TEST.exe!Eigen::internal::pstore<double,__m256d>(double * to, const __m256d & from) Line 251	C++
 	AVX_TEST.exe!Eigen::internal::pstoret<double,__m256d,32>(double * to, const __m256d & from) Line 475	C++
 	AVX_TEST.exe!Eigen::internal::assign_op<double,double>::assignPacket<32,__m256d>(double * a, const __m256d & b) Line 28	C++
 	AVX_TEST.exe!Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::assign_op<double,double>,0>::assignPacket<32,32,__m256d>(__int64 row, __int64 col) Line 653	C++
 	AVX_TEST.exe!Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::assign_op<double,double>,0>::assignPacketByOuterInner<32,32,__m256d>(__int64 outer, __int64 inner) Line 667	C++
 	AVX_TEST.exe!Eigen::internal::copy_using_evaluator_innervec_CompleteUnrolling<Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::assign_op<double,double>,0>,0,12>::run(Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::assign_op<double,double>,0> & kernel) Line 276	C++
 	AVX_TEST.exe!Eigen::internal::dense_assignment_loop<Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::assign_op<double,double>,0>,3,2>::run(Eigen::internal::generic_dense_assignment_kernel<Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::evaluator<Eigen::Matrix<double,3,4,0,3,4> >,Eigen::internal::assign_op<double,double>,0> & kernel) Line 435	C++
 	AVX_TEST.exe!Eigen::internal::call_dense_assignment_loop<Eigen::Matrix<double,3,4,0,3,4>,Eigen::Matrix<double,3,4,0,3,4>,Eigen::internal::assign_op<double,double> >(Eigen::Matrix<double,3,4,0,3,4> & dst, const Eigen::Matrix<double,3,4,0,3,4> & src, const Eigen::internal::assign_op<double,double> & func) Line 724	C++
 	AVX_TEST.exe!Eigen::internal::Assignment<Eigen::Matrix<double,3,4,0,3,4>,Eigen::Matrix<double,3,4,0,3,4>,Eigen::internal::assign_op<double,double>,Eigen::internal::Dense2Dense,void>::run(Eigen::Matrix<double,3,4,0,3,4> & dst, const Eigen::Matrix<double,3,4,0,3,4> & src, const Eigen::internal::assign_op<double,double> & func) Line 863	C++
 	AVX_TEST.exe!Eigen::internal::call_assignment_no_alias<Eigen::Matrix<double,3,4,0,3,4>,Eigen::Matrix<double,3,4,0,3,4>,Eigen::internal::assign_op<double,double> >(Eigen::Matrix<double,3,4,0,3,4> & dst, const Eigen::Matrix<double,3,4,0,3,4> & src, const Eigen::internal::assign_op<double,double> & func) Line 820	C++
 	AVX_TEST.exe!Eigen::PlainObjectBase<Eigen::Matrix<double,3,4,0,3,4> >::_set_noalias<Eigen::Matrix<double,3,4,0,3,4> >(const Eigen::DenseBase<Eigen::Matrix<double,3,4,0,3,4> > & other) Line 722	C++
 	AVX_TEST.exe!Eigen::Matrix<double,3,4,0,3,4>::Matrix<double,3,4,0,3,4>(Eigen::Matrix<double,3,4,0,3,4> && other) Line 278	C++
 	[External Code]	
 	AVX_TEST.exe!main(int argc, char * * argv) Line 47	C++
Comment 4 Christoph Hertzberg 2017-02-03 12:33:17 UTC
You must also use:
  std::vector<Ray, Eigen::aligned_allocator<Ray> >
(you should actually also use Eigen::aligned_allocator when compiling for SSE, even though it is not necessary on most 64bit systems).
Comment 5 Björn Piltz 2017-02-03 12:37:03 UTC
Thanks, that does it! Then the documentation for "An alternative - specializing std::vector for Eigen types" is wrong:

    #include<Eigen/StdVector>
    /* ... */
    EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix2d)
    std::vector<Eigen::Vector2d>
Comment 6 Björn Piltz 2017-02-03 12:39:52 UTC
Or actually it seems <StdVector> needs to be fixed:

    #if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 /* MSVC auto aligns in 64 bit builds */

    #define EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(...)
Comment 7 Gael Guennebaud 2017-02-03 14:18:05 UTC
I see, so we should remove  EIGEN_OS_WIN64 if EIGEN_MAX_STATIC_ALIGN_BYTES>16
Comment 8 Björn Piltz 2017-02-03 14:23:19 UTC
I think the only safe case to not apply the EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION fix is:
#if EIGEN_COMP_MSVC && EIGEN_OS_WIN64 && EIGEN_MAX_STATIC_ALIGN_BYTES==16
but don't take my word for it!
Comment 9 Gael Guennebaud 2017-02-03 14:24:07 UTC
Let me know if the following truly work. If so I'll backport it.

https://bitbucket.org/eigen/eigen/commits/5430cad55312/
Summary:     Bug 1389: MSVC's std containers do not properly align in 64 bits mode if the requested alignment is larger than 16 bytes (e.g., with AVX)
Comment 10 Björn Piltz 2017-02-03 14:27:52 UTC
Yeah, that works.
Comment 11 Gael Guennebaud 2017-02-03 14:32:29 UTC
btw, in C++11 the prototype of std::vector::resize as been fixed, and it must now be:

void resize( size_type count, const value_type& value );

instead of

void resize( size_type count, const value_type value );

in c++98/03. But according to msdn:

https://msdn.microsoft.com/en-us/library/9xd04bzs.aspx#vector__resize

even with MSVC 2015, std::vector::resize still follows the broken C++98/03 standard. Could someone confirm this from the MSVC's header of vector?
Comment 12 Gael Guennebaud 2017-02-03 14:33:50 UTC
backport: https://bitbucket.org/eigen/eigen/commits/29f0625a5c72/
Comment 13 Björn Piltz 2017-02-03 14:38:06 UTC
The MSDN documentation seems to be wrong. "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector" has the right signature.
Comment 14 Gael Guennebaud 2017-02-03 16:07:07 UTC
ok, thank you.

Note You need to log in before you can comment on or make changes to this bug.