namespace Eigen { /** \page TopicVectorization Vectorization %Eigen performs \em explicit vectorization: instead of relying on the compiler to auto-vectorize scalar loops, %Eigen's evaluators generate SIMD instructions directly through a portable wrapper layer (the "packet math" layer). This page gives an overview of which instruction sets are supported, how vectorization is enabled, what gets vectorized, and how to control it. \eigenAutoToc \section TopicVectorizationArch Supported instruction sets On CPUs, %Eigen provides vectorized kernels for the following instruction sets:
ArchitectureInstruction setsNotes
x86 / x86-64SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2+FMA, AVX512 (incl. the DQ, VL, FP16, and BF16 extensions) Selected from the compiler's target flags (e.g. \c -mavx2 \c -mfma, \c /arch:AVX2)
ARM / AArch64NEON; SVE and SME as opt-in backends SVE requires \c EIGEN_ARM64_USE_SVE and a fixed vector length (-msve-vector-bits=N); the SME backend, enabled with \c EIGEN_ARM64_USE_SME, accelerates \c float and \c double matrix products and must be built \em without -msve-vector-bits, since a fixed length would pin the kernels to one runtime streaming vector length. Double precision additionally needs the optional FEAT_SME_F64F64 extension (+sme-f64f64, or a -mcpu that implies it); without it \c double keeps the generic kernel
PowerPCAltiVec, VSX, MMA
IBM Z (s390x)ZVector
MIPSMSA
LoongArchLSX
RISC-VRVV 1.0 Requires \c EIGEN_RISCV64_USE_RVV10 and a fixed vector length (-mrvv-vector-bits=zvl)
Qualcomm HexagonHVX
In addition, the same packet abstraction is used to generate efficient device code for CUDA and HIP GPUs (see \ref TopicCUDA) and for SYCL devices. Vectorization is enabled automatically whenever the compiler's target flags advertise one of the supported instruction sets. You can check what a given translation unit ended up using by printing Eigen::SimdInstructionSetsInUse(): \code std::cout << Eigen::SimdInstructionSetsInUse() << std::endl; \endcode \section TopicVectorizationWhat What gets vectorized Vectorization applies across %Eigen, most notably to: - assignment of coefficient-wise expressions (e.g. a = 2*b + c.cwiseProduct(d)), including the fused evaluation loops described in \ref TopicEigenExpressionTemplates; - reductions such as sum(), minCoeff(), squaredNorm(), and their partial (colwise/rowwise) variants; - matrix-matrix and matrix-vector products, and through them most decompositions; - many coefficient-wise math functions; the \ref CoeffwiseMathFunctions "math function catalogue" lists, for every function, the instruction sets and scalar types with a vectorized implementation. The scalar types with SIMD support depend on the instruction set; \c float, \c double, 32- and 64-bit integers, and std::complex/std::complex are covered on the main backends, with \c Eigen::half and \c Eigen::bfloat16 vectorized where hardware support exists (e.g. AVX512FP16, NEON). Types without SIMD support, such as long double or custom scalar types, simply use scalar code. Fixed-size objects are vectorized when their size is a multiple of the packet size; this is where the alignment rules for \ref TopicFixedSizeVectorizable "fixed-size vectorizable types" come from. Dynamic-size objects use aligned heap allocation plus vectorized loops with scalar prologues and epilogues where needed. Unaligned loads and stores are used where alignment cannot be established; this is enabled by default and controlled by \c EIGEN_UNALIGNED_VECTORIZE. \section TopicVectorizationCtrl Controlling vectorization Vectorization is meant to be transparent, but the following macros, all documented in \ref TopicPreprocessorDirectives, let you control it: - \c EIGEN_DONT_VECTORIZE disables explicit vectorization entirely. - \c EIGEN_MAX_ALIGN_BYTES and \c EIGEN_MAX_STATIC_ALIGN_BYTES bound the alignment %Eigen requests for heap and static data respectively; note that changing them affects the ABI. - \c EIGEN_UNALIGNED_VECTORIZE=0 restricts vectorization to expressions whose destination is aligned. - \c EIGEN_FAST_MATH selects between faster and more accurate vectorized math functions. Disabling vectorization also drops %Eigen's alignment: outside GPU compilation, \c EIGEN_DONT_VECTORIZE sets the ideal alignment to zero, and the defaults for \c EIGEN_MAX_STATIC_ALIGN_BYTES and \c EIGEN_MAX_ALIGN_BYTES follow it. Fixed-size vectorizable types then lose their over-alignment — \c alignof(Vector4f) drops from 16 to 4 on a typical x86-64 build — so translation units that disagree about \c EIGEN_DONT_VECTORIZE disagree about the ABI. Define the alignment macros explicitly and identically everywhere if you need the boundary to stay fixed. See \ref TopicUnalignedArrayAssert for what the alignment is there for. When compiling CUDA sources, host-side SIMD must be disabled; see \ref TopicCUDA. \section TopicVectorizationInternals Under the hood Vectorized kernels are written in terms of generic packet primitives — pload(), pstore(), padd(), pmul(), predux(), and friends — declared in Eigen/src/Core/GenericPacketMath.h and specialized for each instruction set under Eigen/src/Core/arch/. Expression evaluators query each expression's packet support and alignment at compile time to choose between scalar, linear, sliced, and unrolled vectorized evaluation loops. Custom functors can participate in vectorization by providing a \c packetOp() and advertising \c PacketAccess in their traits; see \ref TopicCustomizing_Functors. */ }