clpeak 2.1.4
47 commits since 2.1.3. This is a measurement-accuracy release: several tests were reporting numbers that were wrong in a way no device could reveal on its own. Readings from 2.1.4 are not comparable with older runs for the rows listed below.
Corrected measurements
INT8 dot-product (all backends). Every backend kept an operand moving with an extra op (y ^= a) that the op budget did not count, so the reported rate was the dot rate divided by whatever issue that op stole. All chains now run two accumulators feeding each other — three distinct registers per dot, nothing else in the loop. On an RTX 5060 the CUDA row goes 33587 → 41683 GOPS (99.3% of the card's derived ceiling); the Vulkan shader additionally moved to 64 dots per trip so the loop counter stops competing with the dots.
Mixed precision (all six backends). Every mp kernel narrowed its accumulator through fp16 once per 16 chain instructions — an uncounted conversion sitting in the dependent chain — and OpenCL's narrowed once per MAC, capping it at half the fp32 rate. Deepened to 128 chain instructions per narrowing round, matching bf16. An Arc A380 was reading 57% of its own fp32 rate.
Image bandwidth (all six backends). The row-major-only walk was the pathological case for the block-linear arrays CUDA and OpenCL use, and the ideal case for what Vulkan got — the long-standing ~1.5x cross-API gap was deflation, not inflation. Both walk orders now race and the faster is reported (--verbose prints both). On a 5060 this closes CUDA/Vulkan/OpenCL from 270/415/271 to within ~1%.
Vulkan cooperative matrix. Three separate fixes: tiles now run at the subgroup width the driver actually advertised them at (via VK_EXT_cooperative_matrix_maintenance1), the MulAdds run as a block of sixteen distinct products so neither the compiler can fold them nor the loop back-edge can break Xe-HPG's DPAS grouping, and saturating-accumulation tiles are filtered out instead of being driven with a non-saturating shader. Shaders target SPIR-V 1.5. Together these fix a process-killing crash on Arc A380 int8 and take A380 fp16 coopmat from 12.5 to ~25.9 TFLOPS.
Vulkan fp16 compute. The hp shaders ran at half the register footprint of the sp shaders they get compared against, so the sweep never varied ILP at all. Chain counts doubled — A380 was flat at 4.94 TFLOPS against 9.84 from oneAPI on the same card.
Affine chain seeding (OpenCL, Vulkan, Metal, oneAPI). Chain seeds were spaced 1 apart while a width-W vector seed already spans W values, so at width ≥2 two scalar chains started identical and stayed bitwise identical — a compiler could CSE one away while the host still credited it. Surfaced on NVIDIA fp64 (RTX 4060 double2 inflated 4/3, 351.7 vs 271.5 GFLOPS). Seeds now step a full vector width.
Global / local bandwidth. The 128 MB working set no longer clears a large LLC — a Ryzen 7 5700X3D (96 MB V-Cache) read up to 99 GBPS against a 57.6 GBPS DDR4 ceiling. The working set is now 8x the device's last-level cache (512 MB fallback on CPU devices). Local bandwidth is now skipped with an explicit [unsupported] on devices with no real scratchpad, instead of timing work-item serialization against DRAM.
Vulkan bandwidth dispatch. Batched dispatches in the timed phase had no dependency between them, so NVIDIA overlapped two passes over the same buffer while the byte count assumed one. Barriers added for the three bandwidth tests; the compute tests keep the overlap deliberately.
Together these fix a process-killing crash on Arc A380 int8 and take A380 fp16 coopmat from 12.5 to ~25.9 TFLOPS.
Thanks to #205
Changed and removed rows
- OpenCL transfer bandwidth collapsed from an eight-metric map/unmap/memcpy breakdown to
h2d_pinned/d2h_pinned, matching CUDA/ROCm/oneAPI. Always wall-clock timed — CL profiling events read near-zero on unified memory and were reporting multi-terabyte rates. - oneAPI INT8 dot-product removed. SYCL exposes no DP4a intrinsic;
dot_accis portable C++ in the header and IGC does not pattern-match it back. It read 1.83 TOPS where Vulkan read 16 on the same A380. The device is still measured properly through OpenCL and Vulkan.
New
- Vulkan
fp16_f16acccooperative-matrix row. Consumer NVIDIA parts run fp32 accumulation at half rate; a 5060 measures 42.5 TFLOPS with fp32 accumulate and 83.4 with fp16, and the 16-bit total is the number those cards are sold on. The two fp16 rows now read as a pair. - oneAPI joint matrix enumerates every combination the runtime advertises and measures each at its real sub-group size, rather than assuming a fixed shape.
tool/shader_ops.py— compiles a shader with the build's own flags, freezes the spec constants to a real tile, and reports what is actually in the inner loop: work ops, uncounted ops beside them, distinct operand pairs, chain dependency. Exits non-zero on the two shapes that produce wrong readings. Every compute-peak fix in this release was verified this way without the device on hand.-DCLPEAK_VERSION_OVERRIDE=<version>lets distribution packagers stamp the version when building from a release tarball with no git metadata (thanks @plusky).--verbosediagnostics: advertised coopmat properties and the tile picked per dtype, coopmat subgroup width vs the device's range, which 4x8-bit dot forms the driver accelerates, both image walk rates, both OpenCL global-bandwidth offset shapes, and phase markers so a driver-side crash shows where it died.
Full Changelog: 2.1.3...2.1.4