Windows CUDA and SIMD Tile checkpoint

The initial October 1, 2026 matrix runs actual tile::compile kernels through CUDA TIRx/PTX, experimental native CUDA Tile IR with a fixed 16×16×8 tile, and XIR/SIMD. All 22 records passed: 18 Tile configurations and four library reference processes. Separate larger-tile and K-block experiments bring the lowest observed native 512³ time to 460.268 µs with 32×32×1. The original TIRx observation remains lower at 397.882 µs, from a different measurement window. All three windows are retained below. These bounded experiments do not establish a general backend or library performance advantage.

Platform and measurement

The machine has an Intel Core Ultra 7 155H (16 cores, 22 logical processors) and an NVIDIA GeForce RTX 4060 Laptop GPU (SM 8.9), running Windows 11 Pro for Workstations 10.0.26200. The Release build uses MSVC 14.51.36231, LLVM 22.1.8, CUDA 13.4, CMake/Ninja, and the native C++ TIRx bridge; TVM_COMPILE_FORCE_FALLBACK is unset. The native Tile IR route is enabled only for its own processes with LUISA_CUDA_TILE_IR=1 and Lowering::NATIVE. See its supported contract.

Each process starts suspended, receives affinity 0x15400 (logical CPUs 10, 12, 14, 16, four distinct physical P cores), and then resumes. SIMD uses four CPU workers and width eight; OpenBLAS uses four threads. No clock or power-plan settings are changed. Each configuration has 500 ms warmup, seven calibrated batches targeting 100 ms each, and seven separately recorded single-dispatch latency samples. Compilation, allocation, uploads, readback, and numerical validation are outside the warm timing interval.

The tables report the median synchronized host-wall time per GEMM. Luisa measures C++ command construction, submission, execution, and final synchronization. Library references measure Python/NumPy or Python/ctypes submission and synchronization; cuBLAS also records two events per batch. These are different submission paths. Neither a library/Tile ratio nor a CUDA event span containing host submission gaps establishes isolated GPU kernel speed. This is one serial tuning pass, without repeated-process ABBA confidence estimates.

Actual Luisa strict FP32 results

All kernels compute C = A * B with FP32 storage and accumulation, enable_fast_math=false, and no FP16/BF16/TF32 input conversion. The default Tile MMA policy permits reassociation; this comparison does not require all routes to use identical contraction order. Native Tile IR currently emits ascending-K FP32 FMA with round-to-nearest-even and preserved subnormals.

TIRx and SIMD each test four Tile schedules: (1,8,16), (4,8,16), (8,8,16), and (16,16,16). Their rows select the lowest measured median. Native Tile IR tests only (16,16,8), so its row is a fixed candidate rather than a best-of-four result. The candidate counts refer to these external Tile schedules, not the SIMD backend’s internal mapping search.

GEMM

Actual Luisa route

Selected tile M×N×K

Passed candidates

Median host-wall µs

Seven-batch range µs

128³

CUDA TIRx → CUDA C → NVRTC PTX

1×8×16

4/4

40.631

40.484–40.658

128³

XIR → SIMD → LLVM

8×8×16

4/4

89.429

76.579–107.599

128³

CUDA Tile C++ → NVRTC Tile IR → cubin

16×16×8

1/1

17.925

17.720–18.255

512³

CUDA TIRx → CUDA C → NVRTC PTX

8×8×16

4/4

397.882

397.617–408.360

512³

XIR → SIMD → LLVM

16×16×16

4/4

3057.770

2827.640–3260.810

512³

CUDA Tile C++ → NVRTC Tile IR → cubin

16×16×8

1/1

748.928

746.966–772.041

Native Tile IR takes 0.441× the selected TIRx host time at 128³ and 1.882× at 512³. Different schedules and the small candidate set prevent treating this as an intrinsic compiler-route ranking.

Every Tile configuration checks all 16,384 or 262,144 outputs against an FP64 oracle, with zero nonfinite outputs and maximum absolute error 0. Inputs are fixed integer multiples of 1/64; these dimensions make their products and partial sums exactly representable in FP32. The runner also requires error ≤ 1e-6, independently of the executable’s looser legacy exit tolerance. This timing fixture alone does not test general FP32 rounding. Separate native runtime tests cover full-mantissa random inputs, cancellation, ordered FMA, masks, aliases, views, and special bit patterns.

Library brackets and drift

Each dimension is bracketed by fresh reference processes. cuBLAS uses FP32 storage, CUBLAS_PEDANTIC_MATH, CUBLAS_COMPUTE_32F_PEDANTIC, CUBLAS_GEMM_DEFAULT, and NVIDIA_TF32_OVERRIDE=0. The CPU reference is NumPy 2.3.5 with OpenBLAS 0.3.30, its Haswell kernel, and four threads. All reference outputs also have zero maximum error on the fixed fixture.

GEMM

Reference

Before host-wall µs

After host-wall µs

After/before change

128³

cuBLAS strict FP32

11.6266

11.6248

−0.016%

512³

cuBLAS strict FP32

49.3398

50.2860

+1.918%

128³

NumPy/OpenBLAS FP32

66.576

115.025

+72.772%

512³

NumPy/OpenBLAS FP32

935.668

1236.253

+32.125%

Both CUDA routes take more host time than both cuBLAS brackets at these shapes. SIMD at 512³ also takes more time than both OpenBLAS brackets. The 128³ SIMD result lies between its two reference values: averaging that large drift would create an unsupported small apparent win. These library comparisons retain the different host-call overheads described above.

Reproducing the selected kernels

Build with the CMake Tile/TIRx/CUDA/SIMD configuration and the CUDA 13.4 native helper described in the CUDA workflow. From the repository root, the selected rows use these CLI settings; required CUDA and TVMx runtime DLL directories must be on PATH:

cmake --build build-msvc-llvm
$bench = Join-Path $PWD 'build-msvc-llvm/bin/benchmark_tile_xir_gpu.exe'
$env:LUISA_SIMD_WORKER_COUNT = '4'
$env:LUISA_SIMD_WARP_WIDTH = '8'
$env:NVIDIA_TF32_OVERRIDE = '0'
Remove-Item Env:LUISA_CUDA_TILE_IR -ErrorAction SilentlyContinue
Remove-Item Env:TVM_COMPILE_FORCE_FALLBACK -ErrorAction SilentlyContinue
& $bench cuda 128 128 128 1 8 16 7 100 500 0 tirx
& $bench cuda 512 512 512 8 8 16 7 100 500 0 tirx
& $bench simd 128 128 128 8 8 16 7 100 500 0 native
& $bench simd 512 512 512 16 16 16 7 100 500 0 native
$env:LUISA_CUDA_TILE_IR = '1'
& $bench cuda 128 128 128 16 16 8 7 100 500 0 native
& $bench cuda 512 512 512 16 16 8 7 100 500 0 native
Remove-Item Env:LUISA_CUDA_TILE_IR

These commands reproduce kernels and sample settings. Matching the measured environment also requires the suspended-process affinity setup, serial execution, clean benchmark environment, all four TIRx/SIMD schedules, and before/after library brackets. The local evidence packet retains those steps in .deps/oct01-native-runtime-performance.py and all 22 records in .deps/native-runtime-performance/results.json (14:51:50–14:53:12 UTC+8, October 1). These ignored local artifacts are not distributed with the repository. The packet records exact commands, source/binary SHA-256 hashes, raw samples, realization strings, and the prior native correctness report; it rejects changed runtime inputs.

Separate handwritten CUDA Tile API probe

An earlier same-machine API experiment passed all ten records, including six handwritten kernel/shape combinations. It bypasses Luisa’s emitter and runtime. Its FP32 FMA kernel uses a 32×32 output tile with K step one; FP16/BF16 MMA uses K step 16, converts inputs inside the kernel, and accumulates in FP32. All timings below include Python/ctypes submission.

GEMM

Handwritten FP32 FMA µs

Handwritten FP16 MMA µs

Handwritten BF16 MMA µs

Strict cuBLAS before→after µs

128³

29.710

11.171

10.769

11.093→11.591

512³

423.015

185.524

186.067

49.245→49.401

The 12 random/cancellation checks cover 1,671,168 outputs and pass their respective FP64 oracles. Narrow modes are checked against quantized operands. For 512³ random inputs, maximum error against original FP32 operands is 3.37e-5 for FP32 FMA, 8.97e-3 for FP16, and 7.41e-2 for BF16. Consequently, lower MMA timings are not strict-FP32 speedups and must not be presented as Luisa native-runtime results. cuBLAS bracket drift is +4.49%/+0.32% at 128³/512³; this earlier packet’s OpenBLAS drift is −36.85%/−19.98%, also unsuitable for stable CPU superiority claims. The separate local packet is .deps/oct01-native-tile-performance-run2.

Follow-up: three additional native Tile IR schedules

A separate run at 15:00:33–15:01:10 UTC+8 on October 1 tests three new native schedules per shape. All 10 records passed: six actual Luisa native Tile IR configurations and four library reference processes. It keeps the same strict FP32 fixture, seven 100 ms target samples, 500 ms warmup, and four-P-core affinity. Every Tile output is finite and has zero maximum error against FP64. The original 22-record matrix above is retained without replacing its schedules or pooling measurements across runs.

GEMM

Native tile M×N×K

Median host-wall µs

Seven-batch range µs

128³

16×32×16

64.732

64.700–65.209

128³

32×32×16

59.550

59.480–59.587

128³

64×64×16

40.576

40.424–40.651

512³

16×32×16

3413.070

3411.550–3413.600

512³

32×32×16

2302.080

2301.360–2302.700

512³

64×64×16

663.668

663.019–664.471

The best of these 3/3 candidates is 64×64×16 at both shapes. The older 16×16×8 result is 17.925 µs at 128³ and 748.928 µs at 512³. Matching executable/backend/helper hashes establish the same implementation, but these are different measurement windows: the historical comparison is not a controlled speedup estimate. The new candidates do not improve on the old small-shape observation. The new 512³ observation also exceeds the earlier TIRx result of 397.882 µs, subject to the same different-window limitation, and still leaves a large gap to its own cuBLAS brackets.

GEMM

Reference

Before host-wall µs

After host-wall µs

After/before change

128³

cuBLAS strict FP32

10.7096

11.6958

+9.208%

512³

cuBLAS strict FP32

49.0995

49.4378

+0.689%

128³

NumPy/OpenBLAS FP32

105.579

48.815

−53.765%

512³

NumPy/OpenBLAS FP32

901.043

1000.375

+11.024%

All library output checks pass with zero maximum error. The same host-call and baseline-drift qualifications apply; no isolated GPU-kernel ratio is inferred. The local packet .deps/native-runtime-tuning/results.json retains all six candidates, their before/after references, and a hashed snapshot of the earlier native results. Replay these kernels with the previous CLI, replacing the three tile arguments with each row’s schedule and keeping LUISA_CUDA_TILE_IR=1, variant 0, and lowering native.

The emitter’s FP32 path loads operand tiles, then loops over K, extracts one column and row, and performs one broadcast FP32 FMA per contraction element. It does not select ct::mma for FP32, and the pipeline emits an ordinary ordered loop. Increasing the K tile therefore does not reduce the total K FMA steps or introduce hardware MMA. All three new candidates use K=16 and also change M/N versus the old candidate; isolating the effect of K requires a separate same-M/N experiment.

Follow-up: K-block schedules

The 15:04:05–15:04:46 UTC+8 run on October 1 adds four native schedules per shape, including a same-M/N comparison of K=1 and K=4. All 12 records passed: eight actual Luisa native configurations and four library reference processes. It uses the same binary guards, strict FP32 fixture, four-P-core affinity, 500 ms warmup, and seven batches targeting 100 ms. All eight configurations validate every output as finite with zero maximum FP64 error. Earlier tables remain separate historical observations.

GEMM

Native tile M×N×K

Median host-wall µs

Seven-batch range µs

128³

16×16×1

19.224

19.165–19.274

128³

32×32×1

28.827

28.290–29.394

128³

64×64×1

54.839

54.723–54.883

128³

32×32×4

20.402

20.244–20.421

512³

16×16×1

736.184

720.517–740.267

512³

32×32×1

460.268

452.061–460.705

512³

64×64×1

490.794

489.803–491.238

512³

32×32×4

670.401

669.785–670.818

Within this run, the best of 4/4 candidates is 16×16×1 at 128³ and 32×32×1 at 512³. Holding M/N at 32×32, K=1 takes 460.268 µs versus K=4’s 670.401 µs at 512³; at 128³ the ordering reverses (28.827 versus 20.402 µs). K blocking matters for these shapes, but smaller K is not universally better. This serial observation does not identify the machine-level cause or establish a statistically controlled improvement over earlier windows.

GEMM

Reference

Before host-wall µs

After host-wall µs

After/before change

128³

cuBLAS strict FP32

10.6199

11.7722

+10.851%

512³

cuBLAS strict FP32

49.7551

49.8300

+0.151%

128³

NumPy/OpenBLAS FP32

103.414

113.712

+9.958%

512³

NumPy/OpenBLAS FP32

1141.153

1137.083

−0.357%

The libraries also pass all output checks with zero error. Even the best native candidate remains above both cuBLAS brackets. Different C++ and Python/FFI call overheads still prevent interpreting these host-wall numbers as isolated GPU-kernel ratios. The evidence packet is .deps/native-runtime-k-tuning/results.json; replay uses the same native CLI and each row’s tile arguments. No earlier measurements are pooled into its four-candidate selection.