Vulkan Linear Math benchmark
Complete F32 and F64 coverage for OA's packed Vulkan-native spatial math, with equivalent arithmetic separated from the validation work that GLM does not perform.
All equivalent arithmetic reached parity or better
The expanded harness covers 50 operation families in both precisions: 100 correctness-gated OA/GLM pairs. All 27 families with equivalent valid-input arithmetic were at parity or faster in both F32 and F64. Across those rows, OA used 13.4% less time by geometric mean for F32and 11.9% less for F64 on the qualified host.
| Evidence slice | Qualified result |
|---|---|
| Coverage | 50 operation families × F32/F64; all 100 whole-workload checksum oracles passed |
| Equivalent arithmetic | 27/27 families at parity or faster in F32 and 27/27 in F64; parity threshold ≤1.03× |
| Arithmetic geometric mean | 0.866× for F32 and 0.881× for F64: 13.4% and 11.9% lower time |
| Mat4 multiplication | 0.622× GLM time in F32; 0.975× in F64 |
| TRS composition | 0.358× GLM time in F32; 0.322× in F64 |
| Translation / scale construction | 0.418–0.472× GLM time across both precisions |
| Hardened operations | 23 checked or fail-closed public routes reported separately from raw GLM peers |
This is fixed-host evidence for one compiler, CPU, dataset, packed ABI, and date—not a universal or fastest-library claim. The result retains OA's Vulkan convention, packed value ABI, overflow fallbacks, validation, and fail-closed behavior.
Small host values, one spatial convention
VLM means Vulkan Linear Math. It is OA's immediate host-side spatial-math layer for cameras, UI, rendering, animation, SDK simulation, and format conversion—not a vision-language model and not a second oa::Matrix engine. Values are trivially copyable and functions are stateless; VLM owns no engine, allocation, operation graph, Vulkan handle, or session.
| Contract | Current VLM surface |
|---|---|
| Values | Vec2/3/4, DVec2/3/4, Quat/DQuat, Mat3/DMat3, and Mat4/DMat4 |
| ABI | Packed standard-layout scalar values with exact F32 sizes; no public SIMD alignment |
| Axes | Right-handed; +X right, +Y up, camera-forward −Z |
| Matrices | Row-major storage and row-vector multiplication: transformed = value * matrix |
| Projection | Vulkan normalized-device-coordinate depth [0, 1] |
| Raster Y | Selected once through viewport state; no hidden constructor flip |
| Interop | Units, axes, handedness, and quaternion order convert once at the boundary |
Operators forward to one named implementation in oa::vlm. There is no FnVlm: this is immediate scalar math, unlike schema-owned device work. The surface covers vector geometry, robust quaternion math, all six Euler orders, fixed-shape matrix algebra, checked inverses, affine decomposition, TRS, view and projection families, and top-origin viewport project/unproject.
Optimized without weakening the contract
| Implementation seam | Current route | Preserved behavior |
|---|---|---|
| Normalization | Direct ordinary-value squared norm; scale-first fallback for finite subnormal or extreme values | Zero/non-finite failure and robust overflow/underflow behavior |
| Fixed-shape matrices | Unrolled Mat3/Mat4 add, transpose, transform, and multiply paths | Packed row-major ABI and row-vector convention |
| Determinant | Fast finite direct formula with guarded out-of-line scaled-pivot fallback | Overflow and non-finite handling retained |
| Affine work | Specialized affine inverse, translation, scale, and direct TRS composition | Checked singularity, conditioning, and output preservation retained |
| Geometry and rotation | Faster checked projection, angle, look-at, quaternion, and interpolation routes | Degenerate geometry and invalid tolerances still fail closed |
| SIMD evidence | Dedicated BenchSimd retains the former FnSimd/xsimd comparison | VLM stays packed scalar math; batch SIMD remains a separate contract |
The largest wins come from fixed-shape work: Mat4 multiplication is explicitly unrolled, TRS composition writes the known affine form directly, and translation and scale constructors no longer route through generic matrix work.
Qualified protocol
| Field | Recorded value |
|---|---|
| OA tree | Dirty qualification tree based on 15b18f0fa1676a5c2c568345fdfc4f22a0256d6f |
| Peer | GLM 1.1.0 source archive; not an OA product or package dependency |
| Peer manifest | 2134e2062c2a98ee535a16308780dccfd844f5945d303369a83547a0c8109c49 |
| Executable | bin/release/test/core/vlm/benchVlm |
| Compiler / build | Clang 22.1.8; Release; C++20; -O3 -DNDEBUG -march=native |
| Host | Intel Core i5-1145G7; 4 physical cores / 8 threads; Linux 7.1.8 |
| Pinning / power | CPU 2; intel_pstate powersave governor; balanced platform profile |
| Workload | 65,536 deterministic values per case; 50 cases; F32 and F64 |
| Inner estimator | 3 warmups; 15 measured samples; median; alternating OA/GLM order |
| Outer estimator | 2 fresh-process warmups; 7 measured fresh processes; 3-second cooldown |
| Thermal gate | Package temperature ≤65 C before each process; measured starts 58–64 C |
| Correctness | Whole-case checksum oracle before timing; all 100 precision/case pairs passed |
| Stability metric | Mat4 multiply: 8.714 ns/item median; 1.83% relative MAD; 13.34% min–max spread |
A later full repeat reached 45.8% absolute timing spread under laptop throttling and was rejected. The tables retain the earlier thermally stable seven-process campaign. The Mat3-addition row is a focused seven-process follow-up after its fixed-width unroll; it supersedes that one full-suite row without changing the other 49 cases.
Equivalent arithmetic
Each time cell reports OA then GLM median nanoseconds per item. Ratios divide OA time by GLM time, so lower is better; values through 1.03× are classified as parity.
| Operation | F32 OA / GLM ns | F32 ratio | F64 OA / GLM ns | F64 ratio |
|---|---|---|---|---|
| Vec2 add | 1.003 / 1.003 | 1.000× | 1.011 / 1.014 | 0.997× |
| Vec2 dot | 1.003 / 1.003 | 1.000× | 0.986 / 1.022 | 0.965× |
| Vec3 add | 0.935 / 0.996 | 0.938× | 1.962 / 1.990 | 0.986× |
| Vec3 component multiply | 0.973 / 1.004 | 0.969× | 1.804 / 1.900 | 0.950× |
| Vec3 dot | 1.005 / 1.004 | 1.001× | 1.604 / 1.658 | 0.967× |
| Vec3 cross | 1.076 / 1.130 | 0.952× | 1.815 / 1.836 | 0.988× |
| Vec3 reflect | 1.871 / 2.148 | 0.871× | 2.481 / 2.617 | 0.948× |
| Vec3 lerp | 1.134 / 1.380 | 0.822× | 1.942 / 2.091 | 0.929× |
| Vec3 refract | 3.084 / 3.086 | 0.999× | 3.363 / 3.510 | 0.958× |
| Vec4 add | 1.147 / 1.124 | 1.020× | 3.145 / 3.183 | 0.988× |
| Vec4 dot | 1.038 / 1.091 | 0.951× | 2.660 / 2.679 | 0.993× |
| Quaternion multiply | 2.572 / 2.522 | 1.020× | 3.470 / 3.782 | 0.918× |
| Mat3 × Vec3 | 2.406 / 2.604 | 0.924× | 4.936 / 5.196 | 0.950× |
| Mat3 add | 3.813 / 3.858 | 0.988× | 6.909 / 6.973 | 0.991× |
| Mat3 transpose | 1.927 / 1.884 | 1.023× | 4.398 / 4.441 | 0.990× |
| Mat3 multiply | 5.392 / 5.753 | 0.937× | 7.754 / 8.715 | 0.890× |
| Mat3 determinant | 1.611 / 1.595 | 1.010× | 4.464 / 4.418 | 1.010× |
| Mat4 × Vec4 | 4.820 / 5.043 | 0.956× | 8.153 / 8.447 | 0.965× |
| Mat4 add | 7.595 / 7.678 | 0.989× | 11.921 / 12.105 | 0.985× |
| Mat4 transpose | 4.928 / 5.106 | 0.965× | 8.543 / 8.541 | 1.000× |
| Mat4 multiply | 8.714 / 14.015 | 0.622× | 13.530 / 13.880 | 0.975× |
| Mat4 determinant | 5.830 / 5.679 | 1.026× | 9.499 / 9.294 | 1.022× |
| Transform point | 4.777 / 4.892 | 0.977× | 8.353 / 8.578 | 0.974× |
| Transform direction | 4.726 / 4.875 | 0.969× | 8.323 / 8.778 | 0.948× |
| Compose TRS | 8.263 / 23.068 | 0.358× | 11.437 / 35.469 | 0.322× |
| Translation matrix | 0.912 / 2.183 | 0.418× | 0.940 / 1.992 | 0.472× |
| Scale matrix | 0.960 / 2.120 | 0.453× | 1.031 / 2.282 | 0.452× |
Checked and fail-closed operations
These rows are deliberately separate. OA normalizes non-unit quaternions, handles finite subnormal and extreme magnitudes, rejects invalid tolerances and degenerate geometry, estimates inverse conditioning, verifies inverse residuals, preserves outputs on failure, and fails closed from direct APIs. The GLM peer performs its raw valid-input operation. A ratio above one measures current safety cost, not an equivalent-work regression.
| Operation | F32 OA / GLM ns | F32 ratio | F64 OA / GLM ns | F64 ratio |
|---|---|---|---|---|
| Vec2 normalize | 2.197 / 1.507 | 1.457× | 2.677 / 2.728 | 0.981× |
| Vec3 length | 1.836 / 1.025 | 1.791× | 1.894 / 1.512 | 1.252× |
| Vec3 distance | 1.197 / 1.220 | 0.981× | 2.080 / 2.035 | 1.022× |
| Vec3 normalize | 3.145 / 2.102 | 1.496× | 3.177 / 2.791 | 1.138× |
| Vec3 project · checked | 3.229 / 2.072 | 1.558× | 3.656 / 2.633 | 1.388× |
| Vec3 angle · checked | 16.780 / 14.437 | 1.162× | 14.348 / 13.250 | 1.083× |
| Vec4 normalize | 3.710 / 2.536 | 1.463× | 3.598 / 2.978 | 1.208× |
| Quaternion inverse · checked | 8.688 / 3.112 | 2.792× | 10.554 / 4.181 | 2.524× |
| Quaternion normalize | 3.452 / 2.389 | 1.445× | 3.538 / 2.835 | 1.248× |
| Quaternion rotate | 4.518 / 3.702 | 1.220× | 4.963 / 3.884 | 1.278× |
| Quaternion nlerp | 7.889 / 3.252 | 2.426× | 10.309 / 4.695 | 2.196× |
| Quaternion slerp | 31.960 / 19.992 | 1.599× | 46.304 / 38.070 | 1.216× |
| Quaternion to Mat4 | 5.658 / 4.775 | 1.185× | 8.895 / 4.931 | 1.804× |
| Mat3 inverse · checked | 24.288 / 6.118 | 3.970× | 28.541 / 7.638 | 3.737× |
| Mat4 inverse · checked | 33.801 / 30.600 | 1.105× | 38.523 / 26.798 | 1.438× |
| Affine inverse · checked | 48.343 / 11.110 | 4.351× | 54.682 / 13.195 | 4.144× |
| Normal matrix · checked | 30.341 / 6.217 | 4.880× | 36.227 / 8.045 | 4.503× |
| Decompose TRS · checked | 76.976 / 61.503 | 1.252× | 85.118 / 71.021 | 1.198× |
| Look at · checked | 29.614 / 15.684 | 1.888× | 35.753 / 17.867 | 2.001× |
| Perspective · checked | 22.175 / 11.559 | 1.918× | 21.546 / 9.928 | 2.170× |
| Project point · checked | 4.496 / 3.358 | 1.339× | 5.321 / 3.597 | 1.479× |
| Viewport project · checked | 12.442 / 6.897 | 1.804× | 14.192 / 6.830 | 2.078× |
| Viewport unproject · checked | 78.807 / 4.528 | 17.404× | 86.966 / 31.713 | 2.742× |
Checked viewport unprojection is the clearest remaining optimization seam because it performs a checked general inverse for every point. The correct next route is a checked precomputed-inverse or bulk-unproject contract—not deleting singularity, finiteness, residual, or output-preservation guarantees. Conditioned Mat3, affine inverse, and normal-matrix paths remain visible for the same reason.
Correctness before timing
BenchVlm executes each complete OA and GLM workload before timing, compares whole-workload checksums, and rejects non-finite or mismatched results. Timed samples alternate OA-first and GLM-first order. Unknown arguments fail instead of silently changing the workload.
| Gate | Scope | Recorded result |
|---|---|---|
| Release | TestVlm, TestCamera, TestScene, TestTransform, TestSkeleton | 5 / 5 executables passed |
| ASAN | The same five VLM and direct-consumer executables | 5 / 5 passed; no sanitizer report |
| UBSAN | The same five VLM and direct-consumer executables | 5 / 5 passed; no sanitizer report |
| VLM contract | F32/F64 ABI, geometry, quaternion, matrix, affine, projection, and viewport behavior | 39 / 39 TestVlm cases passed |
| Benchmark oracle | 50 operation families in F32 and F64 | 100 / 100 whole-workload pairs passed before timing |
| Source hygiene | Changed VLM source, harness, tests, and evidence | git diff --check passed |
Failure and precision behavior remains explicit
| Operation | Current behavior |
|---|---|
| Normalization | Ordinary finite values use the direct path; subnormal/extreme values use scale-first arithmetic; zero and non-finite inputs fail closed |
| Checked output | Invalid or undefined checked operations leave output unchanged; successful aliasing is supported where specified |
| Inverse | Rejects singular, non-finite, poorly conditioned, or residual-failing results rather than returning an unchecked matrix |
| Projection / view | Rejects invalid ranges, non-finite inputs, singular poses, and degenerate camera bases |
| Matrix to quaternion | Rejects scale, shear, reflection, singularity, and non-finite input before private extraction |
| Euler conversion | Names radians or degrees and one of six explicit application orders; no default interchange order |
| Scalar division | Uses ordinary IEEE floating-point behavior |
The public VLM value surface is C++ only today. There is no dedicated Python VLM binding, and the benchmark is CPU evidence—not evidence about GPU oa::Matrixexecution or oa::FnSimd batch arrays.
Reproduce the comparison
Use the GLM 1.1.0 archive matching the manifest above. Preserve the item count, precision matrix, alternating order, process count, cooldown, thermal gate, and whole-case correctness contract when refreshing the result.
Vlm benchmark terminal
cmake -S . -B build/release \-DOA_VLM_GLM_ROOT=/absolute/path/to/glm-1.1.0cmake --build build/release --target BenchVlm TestVlmpython3 tools/diagnostics/oaBench.py \--output var/benchmark/vlm-glm.json \--name core.vlm_glm_suite \--command-id benchVlm_glm_1_1_0_f32_f64 \--contract peer=glm-1.1.0 --contract precision=f32-f64 \--contract cases=50 --contract items=65536 \--contract oracle=whole-case-checksum --contract order=alternating \--warmup 2 --runs 7 --cooldown 3 --timeout 300 \--thermal-limit-celsius 65 --thermal-sensor-regex 'Package id 0' \--thermal-timeout 300 \--metric-regex 'PAIR precision=f32 case=mat4_mul contract=arithmetic oa_ns=([0-9.]+)' \--metric-name mat4_mul_oa --metric-unit ns/op \--require-regex 'BENCHMARK oracle=PASS' \--cmake-cache build/release/CMakeCache.txt -- \taskset -c 2 bin/release/test/core/vlm/benchVlm \--items 65536 --warmups 3 --samples 15 --precision both
Run the focused gates
Vlm verification terminal
cmake --build build/release --target \TestVlm TestCamera TestScene TestTransform TestSkeletonctest --test-dir build/release \-R '^(TestVlm|TestCamera|TestScene|TestTransform|TestSkeleton)$' \--output-on-failurecmake --build build/asan --target \TestVlm TestCamera TestScene TestTransform TestSkeletonctest --test-dir build/asan \-R '^(TestVlm|TestCamera|TestScene|TestTransform|TestSkeleton)$' \--output-on-failurecmake --build build/ubsan --target \TestVlm TestCamera TestScene TestTransform TestSkeletonctest --test-dir build/ubsan \-R '^(TestVlm|TestCamera|TestScene|TestTransform|TestSkeleton)$' \--output-on-failure
This remains a working-tree qualification. Installed-package, compiler-matrix, shader-boundary, source-audit automation, and exact external-format fixtures retain their own release gates.