llvm-project
f2b3ba3a - [MLIR][XeGPU] Add MXFP fp8 WG GEMM tests and use shared input set (#225944)

Commit
17 days ago
[MLIR][XeGPU] Add MXFP fp8 WG GEMM tests and use shared input set (#225944) Adds four workgroup-level tests, updates two and renames one, so that seven tests covering bf16, mx-fp4 and mx-fp8 exercise the same arithmetic on the same operand values and check against the same expected result. 1. simple_mxfp_gemm -> simple_mxfp_gemm_F4 - renamed, for consistency with the F4/F8 suffixes used by the quantize and dequantize tests 2. (new) simple_gemm_bf16 - non-quantized bf16 GEMM at the MXFP problem size, as the unquantized comparison point, and where the shared input set is documented 3. (new) simple_mxfp_gemm_F8 - f8E5M2 operands with f8E8M0FNU scales 4. (new) simple_mxfp_gemm_dequantizeB_F8 5. (new) simple_mxfp_gemm_quantizeA_F8 - fp8 counterparts of the existing fp4 tests 6. simple_mxfp_gemm_dequantizeB_F4 and simple_mxfp_gemm_quantizeA_F4 are updated in place. What the update changes: * Meaningful operand values. The tests previously used all-ones operands, which cannot distinguish a correct kernel from one that swaps the two fp4 values in a byte, misapplies a scale, or mixes up lanes or tiles. Operands are now drawn from the 8 magnitudes e2m1 can represent - 0, 0.5, 1, 1.5, 2, 3, 4, 6 - indexed by (i + k) % 8 and (j + k) % 8, so consecutive K values differ and the packing is exercised. Every value is exact in f4E2M1FN, f8E5M2, bf16 and f32, which is what lets one input set serve all three formats. * Non-unit block scales. A carries a per-K-block divisor and B a per-K-block scale, three of each, all powers of two, cycling per block of 32. The quantized formats realise the same values through their own scales, so a scale that is ignored or applied to the wrong block now changes the result. * One reference result. Each test computes its expected C with a host f32 GEMM over f32 shadows of the operands, filled in the same loop that writes the device operands so the two cannot drift. Every product is a multiple of 0.25 and the largest result is well under 2^24, so the accumulation is exact and the comparison is bit-for-bit rather than approximate. * A labelled result line. verifyMemRefF32's mismatch count is printed as "mismatches: <n>" via printString/printI64/printNewline and matched with {{^mismatches: 0$}}. A bare "0" check is a substring match over all of stdout, so it passes on any 0 the runtime happens to print, including one inside a larger number, and cannot distinguish a correct run from a kernel that never ran. * A fix for the fp4 A operand in simple_mxfp_gemm_F4. gpu.alloc/memcpy/dealloc size a memref by rounding the element type up to a whole byte - the size is lowered as gep(null, numElements) on i4, which LLVM strides by 1 byte - so a packed fp4 memref is sized at twice its real footprint. The test allocated A as memref<256x4096xf4E2M1FN>, giving a 512 KB overread of a 524288-byte host buffer; because mgpuMemcpy is asynchronous the fault surfaces later, at the stream sync inside the first mgpuMemFree, so the test passed regardless. A now crosses as memref<524288xi8> and is viewed as fp4 on the device, which is what the B operand already does. All seven follow the existing convention in this directory: the mlir-opt compile is the active RUN line and the mlir-runner pipeline is kept behind RUN-DISABLED with a MISMATCH check prefix, so no device is needed and the compile-only run cannot pick up the result check.
Author
Parents
Loading