SIMD-accelerated classes
SIMD acceleration in EBGeometry is implemented with hand-written compiler intrinsics
(__m128/__m256/__m512 and their double counterparts), not compiler
auto-vectorisation. As of today it is confined to the two places listed below; everything else
in the library is scalar code. This is a statement about the current state of the
implementation, not an architectural ceiling – further classes may become SIMD-accelerated in
the same style in the future. This page lists the SIMD-accelerated classes as they exist today,
and explains precisely what gets vectorised in each.
On this page
Per-triangle signed-distance evaluation: TriangleSoAT<T, W>
Source/EBGeometry_TriangleSoA.hpp / EBGeometry_TriangleSoAImplem.hpp
See Triangle meshes for the conceptual picture of why triangles are packed this way.
What it stores: the vertex positions, vertex normals, edge normals, and face normal of
\(W\) triangles, laid out as a structure of arrays (one flat, alignas-aligned array
per coordinate/component, rather than \(W\) separate Triangle objects). See
Mesh Signed Distance Function Classes for the rest of the TriMeshSDF machinery this is packed into.
What is vectorised: the entire closest-point-on-triangle signed-distance query,
TriangleSoAT::signedDistance(point). This is the full algorithm – classifying the
projection of the query point against the triangle’s three edge regions and interior region,
computing the squared distance and sign for whichever region applies, per triangle – executed
for all \(W\) triangles in the block simultaneously, one SIMD lane per triangle. The
result is the minimum signed distance over the whole block, found with vectorised compare/blend
instructions rather than a loop.
What this means in practice: evaluating a TriangleSoAT<T, W> block costs roughly the
same number of instructions as evaluating a single triangle scalar, but produces the answer
for \(W\) of them. This is the leaf-level cost inside every TriMeshSDF::signedDistance()
BVH leaf visit.
Choosing and tuning \(W\): the width is chosen from ISA auto-detection at compile time
(the compiler-predefined macros described in SIMD acceleration), via
EBGeometry::TriangleSoA::DefaultWidth<T>(), and TriMeshSDF/
Parser::readIntoTriangleBVH default to the ISA-appropriate \(W\) for whichever precision
T is in use. See Mesh Signed Distance Function Classes for the full ISA/precision-to-default table, how
to override \(W\) explicitly, and the data-alignment requirements it relies on.
SIMD-accelerated bounding-box pruning: BVH::PackedBVH<T, P, K>
Source/EBGeometry_BVH.hpp / EBGeometry_BVHImplem.hpp
See Bounding volume hierarchies for the conceptual picture of bounding volume hierarchies and tree pruning.
What it stores: each interior node’s \(K\) children’s bounding boxes, laid out as a
structure of arrays (ChildAABBSoA: flat, alignas-aligned low/high-corner coordinate
arrays across all \(K\) children), alongside the usual index-offset node data. See
PackedBVH for the rest of the packed representation.
What is vectorised: the point-to-bounding-box squared-distance test used to decide which
children to descend into (or prune) during traversal, in PackedBVH::signedDistance(). All
\(K\) children of a node are tested against the query point in a single SIMD batch –
one _mm(256\|512)_load_p[sd] per coordinate array, then vectorised subtract/max/multiply/add
to get all \(K\) squared distances at once – rather than a scalar loop over children.
What this means in practice: the cost of deciding which subtree(s) to visit next no longer scales with \(K\) the way a scalar loop would; a wider branching factor (larger \(K\)) is close to “free” for this step as long as it still fits in one SIMD batch for the target ISA, which is exactly why \(K\) is chosen per-ISA (see below).
Choosing and tuning \(K\): the branching factor is likewise chosen from ISA
auto-detection at compile time, via BVH::DefaultBranchingRatio<T>() – a separate function
from TriangleSoA’s, but driven by the same underlying ISA macros, so TriMeshSDF/
Parser::readIntoTriangleBVH still end up with a matching \((K, W)\) pair for whichever
precision T is in use. See Mesh Signed Distance Function Classes for the full ISA/precision-to-default
table and how to override \(K\) explicitly.