| # SIMD and GPU Changes | |
| Use this guide for packet math, architecture backends, device annotations, CUDA/HIP/SYCL code, Tensor device | |
| execution, and the `contrib/Eigen/GPU` module. The repository-root `AGENTS.md` still applies. | |
| ## Packet math | |
| Eigen's vectorization API is the `Eigen::internal` packet layer. `packet_traits` and `unpacket_traits` describe a | |
| packet type and its capabilities; `p*` operations such as `pload`, `pstore`, `padd`, and `pmul` provide the common | |
| interface used by evaluators. | |
| - Scalar fallbacks and the default traits live in `Eigen/src/Core/GenericPacketMath.h`. Shared vector | |
| implementations live under `Eigen/src/Core/arch/Default/`; backend specializations live in the relevant sibling | |
| directories under `Eigen/src/Core/arch/`. | |
| - Start a new operation with a correct generic fallback when one is possible. Add specializations only for relevant | |
| backends that support the operation; do not require an implementation in every backend merely because one backend | |
| gains an intrinsic. | |
| - Guard each intrinsic with the feature macro that enables it, even inside a broader backend directory. For example, | |
| AVX2 or FMA intrinsics in `arch/AVX/` still require `EIGEN_VECTORIZE_AVX2` or `EIGEN_VECTORIZE_FMA`, plus a fallback | |
| for narrower configurations. Consult `Eigen/src/Core/util/ConfigureVectorization.h` for the current feature macros. | |
| - Keep capability flags (`Has*`), packet and half-packet types, alignment, masked access, casts, and cost metadata | |
| consistent with the implementation. A capability flag must not advertise an unavailable or semantically different | |
| operation. | |
| - Preserve scalar-remainder behavior and unaligned paths. Packet-sized inputs alone do not cover an evaluator. | |
| - Standard mathematical functions should match the scalar contract for special values. Measure ordinary-input error | |
| in ULPs against an appropriate scalar or higher-precision reference. Where the platform exposes the IEEE 754 | |
| behaviors, test NaN, infinities, signed zero, subnormals, and domain boundaries explicitly. | |
| A missing specialization is not always a compile error. Some generic fallbacks in `Eigen/src/Core/GenericPacketMath.h` | |
| are the identity or a single-lane version of the real operation; the generic `preverse`, for example, returns its | |
| argument unchanged. A backend without the specialization then silently computes wrong results instead of failing to | |
| build. Before calling a `p*` operation from code that every backend instantiates, confirm that each backend reaching | |
| the call implements the operation. SYCL's packet operations are the usual gap. Keep a scalar fallback for backends that | |
| lack it. | |
| The current source tree and `test/CMakeLists.txt` are authoritative for supported backends and configuration options; | |
| do not copy an architecture inventory into documentation. | |
| ## Device-callable code | |
| For CUDA and HIP, `EIGEN_DEVICE_FUNC` supplies the host/device qualifiers required by functions reached from device | |
| code. Under SYCL device compilation it supplies the flattening and inlining attributes Eigen requires, but does not by | |
| itself decide whether a function is callable from the device. Preserve it on coefficient accessors, evaluators, | |
| functors, small helpers, constructors, and operators reached from device code. | |
| - Keep device code allocation-free unless the specific backend and API deliberately provide an allocator. | |
| - Avoid host-only standard-library calls, exceptions, RTTI assumptions, and function-local static state on device | |
| paths. | |
| - Define configuration macros before the first Eigen public header. | |
| - Keep the index configuration consistent across translation units that exchange Eigen objects. | |
| - Include public module headers in tests and examples. Implementation headers under `Eigen/src/` and | |
| `contrib/Eigen/src/` are not user include points. | |
| ## Three GPU models | |
| ### Core types inside kernels | |
| CUDA and HIP kernels can use fixed-size owning matrices, vectors, and arrays through public Eigen headers; see | |
| `doc/UsingNVCC.dox`. Dynamic owning `Matrix` and `Array` objects require allocation and are generally unsuitable | |
| inside kernels. Runtime dimensions still work: a `Map` over caller-managed device memory can use dynamic dimensions | |
| when every operation the expression reaches is device-callable. | |
| CUDA/HIP compilation disables host SIMD. Move substantial host-side Eigen work to a normal `.cpp` translation unit. | |
| Use `EIGEN_NO_CUDA` or `EIGEN_NO_HIP` only when the corresponding compiler processes Eigen exclusively for host use. | |
| If device code requires a different dense index type, define `EIGEN_DEFAULT_DENSE_INDEX_TYPE` consistently wherever | |
| objects cross the host/device boundary. | |
| ### Tensor devices | |
| `contrib/Eigen/Tensor` evaluates expressions through an explicit device. `GpuDevice` handles CUDA/HIP and | |
| `SyclDevice` handles SYCL; Tensor GPU kernels remain part of the Tensor implementation. Device-resident storage is | |
| normally supplied through `TensorMap`, and the destination selects execution with `out.device(device) = expression`. | |
| Host-side runtime calls in the device go through `EIGEN_GPU_RUNTIME_CHECK` in `Eigen/src/Core/util/GpuRuntime.h`. | |
| Kernel launches use `LAUNCH_GPU_KERNEL` in `contrib/Eigen/src/Tensor/TensorDeviceGpu.h`, which forwards to | |
| `internal::gpu_launch` in `GpuRuntime.h`. If only a `gpu_assert` inspects a stored result, release builds never check | |
| it. Before changing memory, synchronization, or callback semantics, consult | |
| `contrib/Eigen/src/Tensor/README.md` and the nearby device implementation. | |
| ### `contrib/Eigen/GPU` | |
| This module is a host-side wrapper around NVIDIA libraries, and code selects it explicitly by using the `Eigen::gpu` | |
| types. `gpu::DeviceMatrix` is not a `MatrixBase` expression. Each supported expression maps to a CUDA library | |
| operation, not to Core coefficient evaluation or packet fusion. Define `EIGEN_USE_GPU` before including | |
| `<contrib/Eigen/GPU>`, and consult `contrib/Eigen/src/GPU/README.md`. Its tests under `contrib/test/GPU/` are | |
| intentionally host-compiled `.cpp` files. | |
| GPU work in this module runs asynchronously, so refactors that would be harmless elsewhere can break it. | |
| - Freeing, reusing, or destroying memory, streams, events, and handles must respect stream order: synchronize or fence | |
| with an event first. A cleanup that removes a wait is correct only if the wait was redundant in every ownership mode. | |
| For example, a borrowed handle's deleter is a no-op and supplies none of the synchronization that an owned handle's | |
| teardown does. | |
| - Do not signal a mode with a value the user can legitimately pass. A null stream, for example, is a valid stream whose | |
| meaning depends on the build configuration, not a "none" sentinel. | |
| - Key a cache on content or a generation counter, not on host identity (pointer, extent, nnz). Reassignment reuses | |
| allocations, so a cache keyed on host identity can be fooled. | |
| ## Validation | |
| - Packet API or math changes: run the relevant parts of `packetmath`, the generic packet tests, and | |
| `special_packetmath`; exercise every locally available affected backend. | |
| - Core device-callability changes: build and run the relevant `gpu_basic` or `gpu_example` target with the available | |
| CUDA/HIP compiler. | |
| - Tensor device changes: run the operation's CPU Tensor test plus the matching CUDA/HIP/SYCL test where available. | |
| - `contrib/Eigen/GPU` changes: run the focused target under `contrib/test/GPU/` and any affected library | |
| integration target enabled by the local toolkit. | |
| - Report backends or hardware that were unavailable. Do not claim cross-backend validation from a host-only build. | |
| Performance-sensitive packet or GPU changes require a representative benchmark under identical compiler flags, | |
| device state, and workload conditions. Correctness tests are not performance evidence. |