Skip to content

[Common] Experimental CuTeDSL MXFP8 backends in C++ via TVM-FFI - #3137

Open
kainzhong wants to merge 48 commits into
NVIDIA:mainfrom
kainzhong:cutedsl_mxfp8_common
Open

[Common] Experimental CuTeDSL MXFP8 backends in C++ via TVM-FFI#3137
kainzhong wants to merge 48 commits into
NVIDIA:mainfrom
kainzhong:cutedsl_mxfp8_common

Conversation

@kainzhong

@kainzhong kainzhong commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds an experimental, opt-in CuTeDSL backend for MXFP8 quantization. MXFP8 nvte_quantize calls can be routed to JIT-compiled CuTeDSL (CUTLASS Python DSL) kernels instead of the existing CUDA C++ kernels, bridged into the C++ dispatcher via apache-tvm-ffi (https://github.com/apache/tvm-ffi).

It's off by default (use NVTE_ENABLE_CUTEDSL_QUANT_BACKEND=1 to enable) and transparently falls back to the CUDA kernels for any unsupported config or shape (use NVTE_WARN_IF_CUTEDSL_BACKEND_NOT_CHOSEN=1 to enable warning for unsupported cases).

How it works

  • Python CuTeDSL kernels (transformer_engine/common/CuTeDSL/) register a factory as a TVM-FFI global.
  • On a matching MXFP8 quantize, the C++ dispatcher builds a config key, asks Python to JIT-compile + register a kernel for that config (cached), then invokes it with DLTensor views of the TE tensors.
  • Any miss (backend disabled, unsupported config, non-32-aligned shape) returns false → existing mxfp8::quantize CUDA path runs unchanged.

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

  • Added utility classes and functions to retrieve TVM-FFI global functions using strings
  • Ported MXFP8 CUDA C++ quantization code to CuTeDSL

Breaking changes:

  • Building TE now requires apache-tvm-ffi package installed
  • TE uses now need to install apache-tvm-ffi and nvidia-cutlass-dsl packages if they set NVTE_ENABLE_CUTEDSL_QUANT_BACKEND=1. Otherwise they should be fine (pythonwouldn't load tvm-ffi library to make it available in C++ and register CuTeDSL kernels, and C++ wouldn't be able to use dlopen to load libtvm_ffi.so loaded from python so it will fall back to CUDA kernels)

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@kainzhong
kainzhong force-pushed the cutedsl_mxfp8_common branch from daee750 to 218cd24 Compare June 27, 2026 08:27
@kainzhong
kainzhong force-pushed the cutedsl_mxfp8_common branch 4 times, most recently from 2f8c8da to 8448930 Compare July 8, 2026 21:44
@kainzhong

kainzhong commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

Benchmark on ptyche (B200 GPU, ARM CPU):
The benchmark scripts can be found in https://github.com/kainzhong/TransformerEngine/blob/cutedsl_mxfp8_common_bench/tests/pytorch/mxfp8/run_mxfp8_benchmark.py

                         tag        shape   dir   GPU_cpp_us   GPU_dsl_us   GPU_x   cpp_GB/s   dsl_GB/s   CPU_cpp_us   CPU_dsl_us   CPU_x
-----------------------------------------------------------------------------------------------------------------------------------------
          dbias_bf16_e4m3_sw   4096x14336  both        57.75        47.05    1.23     4130.8     5070.4        19.77        23.02    0.86
          dbias_bf16_e4m3_sw   4096x14336   col        39.31        37.20    1.06     4527.9     4785.3        16.89        20.73    0.81
          dbias_bf16_e4m3_sw   4096x14336   row        46.60        43.50    1.07     3820.0     4092.0        17.55        20.32    0.86
          dbias_bf16_e4m3_sw    4096x4096  both        23.87        20.74    1.15     2854.9     3285.8        20.93        22.20    0.94
          dbias_bf16_e4m3_sw    4096x4096   col        17.62        16.27    1.08     2886.7     3126.5        16.55        19.64    0.84
          dbias_bf16_e4m3_sw    4096x4096   row        19.54        19.14    1.02     2602.1     2657.5        16.55        20.25    0.82
          dbias_bf16_e4m3_sw    4096x8192  both        37.81        31.37    1.21     3605.0     4345.0        19.95        22.01    0.91
          dbias_bf16_e4m3_sw    4096x8192   col        26.70        25.56    1.04     3809.4     3979.9        17.23        20.80    0.83
          dbias_bf16_e4m3_sw    4096x8192   row        31.01        28.86    1.07     3279.5     3524.1        17.34        20.11    0.86
          dbias_bf16_e4m3_sw    8192x8192  both        70.53        59.30    1.19     3865.3     4597.6        19.70        23.57    0.84
          dbias_bf16_e4m3_sw    8192x8192   col        49.02        47.63    1.03     4150.0     4271.3        17.35        20.26    0.86
          dbias_bf16_e4m3_sw    8192x8192   row        57.26        54.08    1.06     3552.7     3761.6        17.71        20.02    0.88
             dbias_bf16_e4m3   4096x14336  both        56.96        48.11    1.18     4188.0     4958.7        20.00        23.56    0.85
             dbias_bf16_e4m3   4096x14336   col        39.12        36.81    1.06     4549.9     4835.0        16.74        19.95    0.84
             dbias_bf16_e4m3   4096x14336   row        51.61        43.53    1.19     3448.6     4088.6        16.73        20.37    0.82
             dbias_bf16_e4m3    4096x4096  both        23.45        20.51    1.14     2906.8     3323.9        19.88        22.98    0.87
             dbias_bf16_e4m3    4096x4096   col        17.55        16.20    1.08     2897.9     3139.1        16.59        19.27    0.86
             dbias_bf16_e4m3    4096x4096   row        21.50        19.23    1.12     2365.6     2644.9        16.92        19.80    0.85
             dbias_bf16_e4m3    4096x8192  both        37.33        31.24    1.19     3651.2     4363.0        19.78        23.39    0.85
             dbias_bf16_e4m3    4096x8192   col        26.74        25.20    1.06     3803.8     4035.9        16.39        19.72    0.83
             dbias_bf16_e4m3    4096x8192   row        34.06        29.10    1.17     2986.4     3495.0        17.27        20.58    0.84
             dbias_bf16_e4m3    8192x8192  both        69.48        59.39    1.17     3924.0     4590.9        19.50        23.61    0.83
             dbias_bf16_e4m3    8192x8192   col        49.12        47.46    1.03     4141.7     4286.5        16.99        19.98    0.85
             dbias_bf16_e4m3    8192x8192   row        63.04        54.15    1.16     3226.9     3756.7        16.86        20.39    0.83
          dgelu_bf16_e4m3_sw   4096x14336  both       145.47        94.98    1.53     2447.2     3748.0        13.40        16.82    0.80
          dgelu_bf16_e4m3_sw   4096x14336   col        91.89        76.65    1.20     3215.2     3854.2        10.51        13.22    0.79
          dgelu_bf16_e4m3_sw   4096x14336   row        93.62        76.58    1.22     3155.7     3857.9        10.50        14.35    0.73
          dgelu_bf16_e4m3_sw    4096x4096  both        45.90        31.29    1.47     2216.0     3250.5        13.06        16.04    0.81
          dgelu_bf16_e4m3_sw    4096x4096   col        30.34        25.68    1.18     2781.8     3287.5        10.09        13.34    0.76
          dgelu_bf16_e4m3_sw    4096x4096   row        31.47        25.69    1.22     2682.5     3285.8        10.22        13.96    0.73
          dgelu_bf16_e4m3_sw    4096x8192  both        85.39        56.75    1.50     2382.4     3584.7        13.10        16.46    0.80
          dgelu_bf16_e4m3_sw    4096x8192   col        54.98        46.14    1.19     3070.5     3659.2        10.18        13.55    0.75
          dgelu_bf16_e4m3_sw    4096x8192   row        56.86        46.11    1.23     2969.2     3661.6        10.04        14.69    0.68
          dgelu_bf16_e4m3_sw    8192x8192  both       166.02       107.60    1.54     2450.6     3781.2        13.44        16.56    0.81
          dgelu_bf16_e4m3_sw    8192x8192   col       104.29        86.54    1.21     3237.4     3901.5        10.20        13.42    0.76
          dgelu_bf16_e4m3_sw    8192x8192   row       105.63        86.63    1.22     3196.3     3897.7        10.33        14.30    0.72
             dgelu_bf16_e4m3   4096x14336  both       142.52        94.93    1.50     2497.8     3750.0        13.46        17.52    0.77
             dgelu_bf16_e4m3   4096x14336   col        90.69        76.78    1.18     3257.7     3847.7        10.51        14.02    0.75
             dgelu_bf16_e4m3   4096x14336   row        92.58        76.40    1.21     3191.2     3866.9        10.72        14.03    0.76
             dgelu_bf16_e4m3    4096x4096  both        45.08        31.17    1.45     2256.3     3263.0        13.36        16.63    0.80
             dgelu_bf16_e4m3    4096x4096   col        30.26        25.79    1.17     2789.8     3273.5        10.14        13.61    0.75
             dgelu_bf16_e4m3    4096x4096   row        31.02        25.42    1.22     2721.4     3321.1        10.52        13.89    0.76
             dgelu_bf16_e4m3    4096x8192  both        83.77        56.75    1.48     2428.4     3584.6        12.93        17.22    0.75
             dgelu_bf16_e4m3    4096x8192   col        54.39        46.25    1.18     3104.0     3650.5        10.18        13.78    0.74
             dgelu_bf16_e4m3    4096x8192   row        56.26        45.84    1.23     3000.8     3682.4        10.22        13.88    0.74
             dgelu_bf16_e4m3    8192x8192  both       162.62       107.35    1.51     2501.8     3789.8        13.02        17.42    0.75
             dgelu_bf16_e4m3    8192x8192   col       103.14        86.69    1.19     3273.6     3894.9        10.33        13.56    0.76
             dgelu_bf16_e4m3    8192x8192   row       104.59        86.24    1.21     3228.3     3915.2        10.48        13.50    0.78
           gelu_bf16_e4m3_sw   4096x14336  both       102.85        75.15    1.37     2319.4     3174.2        13.37        16.20    0.83
           gelu_bf16_e4m3_sw   4096x14336   col        66.47        58.58    1.13     2677.9     3038.7        10.22        12.98    0.79
           gelu_bf16_e4m3_sw   4096x14336   row        70.06        58.84    1.19     2540.6     3025.0        10.00        14.69    0.68
           gelu_bf16_e4m3_sw    4096x4096  both        30.98        24.85    1.25     2199.9     2743.0        13.07        15.30    0.85
           gelu_bf16_e4m3_sw    4096x4096   col        22.69        20.13    1.13     2241.4     2526.0         9.89        13.09    0.76
           gelu_bf16_e4m3_sw    4096x4096   row        23.10        20.17    1.15     2201.9     2521.3        10.20        14.37    0.71
           gelu_bf16_e4m3_sw    4096x8192  both        60.52        45.05    1.34     2252.4     3025.7        12.48        15.62    0.80
           gelu_bf16_e4m3_sw    4096x8192   col        40.29        35.49    1.14     2524.4     2866.1         9.85        13.00    0.76
           gelu_bf16_e4m3_sw    4096x8192   row        42.03        35.59    1.18     2420.1     2857.6        10.14        14.00    0.72
           gelu_bf16_e4m3_sw    8192x8192  both       117.61        84.98    1.38     2318.1     3208.1        13.30        15.88    0.84
           gelu_bf16_e4m3_sw    8192x8192   col        75.08        66.11    1.14     2709.4     3076.9         9.98        13.07    0.76
           gelu_bf16_e4m3_sw    8192x8192   row        78.25        66.35    1.18     2599.7     3065.8         9.96        13.84    0.72
              gelu_bf16_e4m3   4096x14336  both       101.10        76.18    1.33     2359.5     3131.4        13.31        16.64    0.80
              gelu_bf16_e4m3   4096x14336   col        65.20        58.74    1.11     2730.1     3030.0         9.77        13.46    0.73
              gelu_bf16_e4m3   4096x14336   row        68.84        58.89    1.17     2585.8     3022.3        10.18        13.01    0.78
              gelu_bf16_e4m3    4096x4096  both        30.60        25.22    1.21     2227.1     2702.2        12.81        15.29    0.84
              gelu_bf16_e4m3    4096x4096   col        22.29        20.20    1.10     2281.1     2517.2         9.66        12.91    0.75
              gelu_bf16_e4m3    4096x4096   row        22.91        19.69    1.16     2219.6     2583.3        10.22        13.91    0.73
              gelu_bf16_e4m3    4096x8192  both        59.19        45.71    1.29     2303.1     2981.8        12.07        15.37    0.79
              gelu_bf16_e4m3    4096x8192   col        39.62        35.56    1.11     2567.2     2859.9         9.76        13.40    0.73
              gelu_bf16_e4m3    4096x8192   row        41.53        35.37    1.17     2449.0     2875.6         9.78        13.79    0.71
              gelu_bf16_e4m3    8192x8192  both       115.28        86.14    1.34     2365.0     3165.0        12.92        15.31    0.84
              gelu_bf16_e4m3    8192x8192   col        73.23        66.20    1.11     2777.9     3072.9         9.86        13.08    0.75
              gelu_bf16_e4m3    8192x8192   row        78.11        66.50    1.17     2604.4     3058.9         9.96        13.50    0.74
          plain_bf16_e4m3_sw   4096x14336  both        42.08        39.30    1.07     5668.9     6070.0        15.96        16.41    0.97
          plain_bf16_e4m3_sw   4096x14336   col        31.21        30.01    1.04     5702.4     5931.2        13.66        14.51    0.94
          plain_bf16_e4m3_sw   4096x14336   row        30.25        29.86    1.01     5883.5     5961.5        13.32        13.88    0.96
          plain_bf16_e4m3_sw    4096x4096  both        14.88        14.60    1.02     4579.4     4668.7        16.81        15.65    1.07
          plain_bf16_e4m3_sw    4096x4096   col        11.74        11.34    1.03     4333.4     4484.3        13.90        13.26    1.05
          plain_bf16_e4m3_sw    4096x4096   row        11.14        11.14    1.00     4565.2     4565.1        13.95        13.86    1.01
          plain_bf16_e4m3_sw    4096x8192  both        25.59        24.35    1.05     5326.8     5597.4        16.56        15.41    1.07
          plain_bf16_e4m3_sw    4096x8192   col        19.76        18.78    1.05     5146.3     5416.4        13.47        14.17    0.95
          plain_bf16_e4m3_sw    4096x8192   row        19.18        18.57    1.03     5303.1     5475.8        13.30        13.91    0.96
          plain_bf16_e4m3_sw    8192x8192  both        47.63        44.45    1.07     5724.2     6132.9        15.76        15.56    1.01
          plain_bf16_e4m3_sw    8192x8192   col        35.16        33.22    1.06     5786.3     6123.5        13.29        13.41    0.99
          plain_bf16_e4m3_sw    8192x8192   row        33.97        33.50    1.01     5987.9     6071.6        14.33        13.38    1.07
             plain_bf16_e4m3   4096x14336  both        41.91        42.19    0.99     5691.5     5654.6        16.54        16.84    0.98
             plain_bf16_e4m3   4096x14336   col        30.83        29.16    1.06     5773.2     6104.0        12.77        13.39    0.95
             plain_bf16_e4m3   4096x14336   row        28.29        28.03    1.01     6292.4     6351.0        11.91        13.92    0.86
             plain_bf16_e4m3    4096x4096  both        16.46        15.72    1.05     4140.2     4335.2        16.70        16.17    1.03
             plain_bf16_e4m3    4096x4096   col        11.59        11.23    1.03     4389.6     4528.9        13.10        13.98    0.94
             plain_bf16_e4m3    4096x4096   row        10.05        10.12    0.99     5059.4     5023.9        12.27        13.21    0.93
             plain_bf16_e4m3    4096x8192  both        26.72        25.95    1.03     5102.0     5253.9        15.80        15.45    1.02
             plain_bf16_e4m3    4096x8192   col        19.20        18.13    1.06     5298.5     5609.1        13.40        14.04    0.96
             plain_bf16_e4m3    4096x8192   row        17.44        16.90    1.03     5831.2     6016.8        11.87        12.82    0.93
             plain_bf16_e4m3    8192x8192  both        46.70        46.56    1.00     5837.4     5854.9        16.19        16.35    0.99
             plain_bf16_e4m3    8192x8192   col        34.80        32.76    1.06     5844.9     6209.4        12.66        13.93    0.91
             plain_bf16_e4m3    8192x8192   row        31.84        31.33    1.02     6389.5     6493.7        12.02        13.37    0.90

@kainzhong
kainzhong marked this pull request as ready for review July 8, 2026 23:25
@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an experimental, opt-in CuTeDSL (CUTLASS Python DSL) backend for MXFP8 quantization, bridged into the C++ dispatcher via apache-tvm-ffi. When NVTE_ENABLE_CUTEDSL_QUANT_BACKEND=1 is set, matching nvte_quantize calls route to JIT-compiled CuTeDSL kernels (cached after first compilation); all other cases transparently fall back to the existing CUDA C++ kernels.

  • New C++ bridge (tvm_ffi_bridge.h): TVMFFICentral singleton lazy-loads libtvm_ffi.so, maintains a per-config std::shared_mutex-guarded cache of compiled kernel handles, and exposes lazyload_function<Config> which calls into Python to JIT-compile on first use.
  • CuTeDSL kernel (quantize_mxfp8.py): ~2500-line Python port of the MXFP8 CUDA kernel supporting all input dtypes, both rowwise and columnwise quantization, swizzled scales, and fused activations with derivatives.
  • Dispatch shim (quantize_mxfp8_cutedsl.cuh): shape-alignment check (must be 32-divisible), workspace-size query (early return before any JIT), swizzled-scale zeroing, TVM-FFI kernel invocation, and a C++ reduce_dbias step.

Confidence Score: 4/5

The new CuTeDSL dispatch path falls back to CUDA for any unsupported config, so existing quantize calls are not broken. Several open issues from prior rounds remain unresolved including reduce_dbias running on unwritten workspace when the kernel is nooped, device-0 arch query in multi-GPU environments, and a test-collection crash when tvm_ffi is absent.

The fallback-to-CUDA logic is sound and the env-var gate is now correctly applied at registration time. The main risks are the reduce_dbias noop divergence from the CUDA path, the device-0 arch selection which could compile Blackwell PTX for the wrong device, and the hard apache-tvm-ffi build dependency.

Files Needing Attention: transformer_engine/common/cast/mxfp8/quantize_mxfp8_cutedsl.cuh (reduce_dbias noop handling), transformer_engine/common/CuTeDSL/utils_fp8.py (device-0 arch selection at import time), tests/pytorch/mxfp8/test_mxfp8_cutedsl_backend.py (unconditional tvm_ffi import)

Important Files Changed

Filename Overview
transformer_engine/common/tvm_ffi_bridge.h New singleton (TVMFFICentral) that lazy-loads TVM-FFI and caches compiled CuTeDSL kernel handles. Shared-mutex cache, deliberate singleton leak, and env-var gating are all correct. Potential double-compilation under concurrent first calls for the same config is present but already known.
transformer_engine/common/cast/mxfp8/quantize_mxfp8_cutedsl.cuh CuTeDSL dispatch shim: shape-alignment check, workspace-size query (early return before lazyload), swizzled-scale zeroing, TVM-FFI invocation, and reduce_dbias. The reduce_dbias call is unconditional when with_dbias=true regardless of whether the kernel was nooped.
transformer_engine/common/CuTeDSL/cast/mxfp8/quantize_mxfp8.py ~2500-line CuTeDSL MXFP8 kernel implementation and factory. Compilation failures are now caught with try/except, but tvm_ffi.register_global_func is outside that guard. Device-0 query for arch check is still always device 0.
transformer_engine/common/CuTeDSL/utils_fp8.py FP8 conversion helpers; cvt_f32_to_fp8e8m0 is selected at module-import time via device_is_blackwell() (device 0), baking the wrong E8M0 PTX into any kernel compiled on a multi-GPU host where device 0 != active device.
transformer_engine/common/CuTeDSL/utils.py Device capability helpers; device_compute_capability defaults to device_id=0 and is lru_cached per-id, so multi-GPU callers passing no argument always receive device 0's SM version.
transformer_engine/common/init.py CuTeDSL library loading and backend registration are now correctly gated behind the NVTE_ENABLE_CUTEDSL_QUANT_BACKEND env var, with broad try/except guards for graceful fallback.
tests/pytorch/mxfp8/test_mxfp8_cutedsl_backend.py Cross-backend bit-exactness test. Unconditional top-level import tvm_ffi breaks collection when the package is absent. get_cfg_key hardcodes swizzled=False and with_amax=False, which may not match production-path configs.
transformer_engine/common/cast/dispatch/quantize.cuh Added CuTeDSL dispatch for NVTE_MXFP8_1D_SCALING in both forward and backward helpers; falls back to CUDA kernel when CuTeDSL returns false. Logic is correct.
pyproject.toml apache-tvm-ffi added as a mandatory build-system requirement, making it a hard dependency for all users even when the CuTeDSL backend is disabled.
transformer_engine/common/transformer_engine.cpp Exposes nvte_set_cutedsl_quant_backend as a C symbol for test-time runtime toggling of the CuTeDSL backend flag. Clean and minimal.

Sequence Diagram

sequenceDiagram
    participant User as User code
    participant Cpp as quantize.cuh dispatcher
    participant Bridge as TVMFFICentral
    participant Python as Python factory
    participant Cache as kernel cache
    participant CUDA as CUDA C++ kernel

    User->>Cpp: nvte_quantize
    Cpp->>Bridge: mxfp8_quantize_cutedsl config
    Bridge->>Bridge: check env var and libtvm_ffi.so
    Bridge->>Cache: lookup config key
    alt cache miss first call
        Bridge->>Python: get_mxfp8_quantization_function fn_name dtype
        Python->>Python: validate config
        Python->>Python: device_compute_capability device 0
        Python->>Python: cute.compile JIT kernel
        Python->>Python: register_global_func fn_name compiled
        Python-->>Bridge: True or False
        Bridge->>Cache: emplace key fn or nullopt
    else cache hit
        Cache-->>Bridge: fn or nullopt
    end
    alt CuTeDSL supported
        Bridge-->>Cpp: tvm ffi Function
        Cpp->>Cpp: zero_scales_kernel if swizzled
        Cpp->>Python: invoke compiled kernel tensors stream
        Cpp->>Cpp: reduce_dbias if WITH_DBIAS
        Cpp-->>User: true done
    else unsupported or backend disabled
        Bridge-->>Cpp: nullopt or false
        Cpp->>CUDA: mxfp8 quantize
        CUDA-->>User: result
    end
Loading

Reviews (25): Last reviewed commit: "fix" | Re-trigger Greptile

Comment thread build_tools/pytorch.py
Comment thread transformer_engine/common/CuTeDSL/cast/mxfp8/quantize_mxfp8.py Outdated
Comment thread build_tools/pytorch.py Outdated
Comment on lines +71 to +74
# apache-tvm-ffi: headers for the C++ API (Module / Function / TensorView)
# and libtvm_ffi.so for symbol resolution. Used by tvm_ffi_bridge.h /
# applyTVMFunction. Python registers AOT-compiled CuTeDSL kernels into
# the global registry; TE C++ looks them up via Function::GetGlobalRequired.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is too verbose and talks about things not needed in the context of the build system.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Comment thread build_tools/pytorch.py Outdated
Comment on lines +121 to +123
# rpath pinned to the pip install dir so the loader finds libtvm_ffi.so
# without LD_LIBRARY_PATH at runtime.
extra_link_args = [f"-Wl,-rpath,{tvm_ffi_lib_dir}"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will (maybe) work in the sdist installation, but what if we decide to do the binary wheel?
All of the other such libraries are linked normally and either loaded using LD_LIBRARY_PATH or
being found and loaded at runtime before we load libtransformer_engine.so.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, what about JAX? It will also use those functions - shouldn't those changes land on the common side instead?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I think I need to delete this from the pytorch side and make them dependencies in common instead

Comment thread setup.py Outdated
"importlib-metadata>=1.0",
"packaging",
"apache-tvm-ffi>=0.1.12",
"nvidia-cutlass-dsl>=4.2.0",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to other things (like cudnn frontend CuTeDSL kernels), I'm pretty sure we need a later version
of that package (4.4.2 I think?). Adding @ksivaman to comment.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change this to 4.4.2

Comment on lines +21 to +22
GTEST_SKIPs the mismatched half), non-32-divisible shapes are omitted (the
dispatcher can never route them to CuTeDSL), and a missing kernel registration

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are the non-32-divisible shapes omitted? Is this a limitation of the cutedsl implementation?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because my CuTeDSL kernels are compiled with

sym_M = cute.sym_int32(divisibility=MXFP8_BLOCK_SCALING_SIZE)
sym_N = cute.sym_int32(divisibility=MXFP8_BLOCK_SCALING_SIZE)

So it assumes 32-divisible shape. Maybe non-32-divisible can be supported as well. I'll run some benchmarks and see if it hurts performance but I think normally people wouldn't use these weird shapes?

#
# See LICENSE for license information.

"""Cross-backend bit-exactness tests for the CuTeDSL MXFP8 quantize kernels.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense in this initial stage, but I would explicitly mark this file as temporary, since
ultimately we will want to standardize on this backend.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could port the CUDA C++ tests to python and make this a standalone test instead of comparing with CUDA kernel's output, but then I thought since we already validated CUDA implementation it would be easier to just make that the reference and compare the result instead.
If we want to standardize on this then should this be python MXFP8 reference implementation on its own?

Comment on lines +7 to +14
Registration is explicit: call :func:`register_cutedsl_backends` to expose the
CuTeDSL kernel entrypoints (e.g. ``get_mxfp8_quantization_function``) as
TVM-FFI global functions. The C++ dispatcher (init_cutedsl_extension in the
PyTorch extension) imports this package and calls it once per process; it then
probes the names via ``tvm::ffi::Function::GetGlobal`` — finding one means the
CuTeDSL toolchain is available and the kernel may be compiled on demand, not
finding it means a plain C++ environment and the dispatcher falls back to the
CUDA C++ kernel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is too verbose and mostly belongs to the register_cutedsl_backends function instead.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines +21 to +27
"""Tanh-approximation GELU. Constants and operator grouping match TE's
`transformer_engine/common/util/math.h::gelu` exactly (factored form
`x · (0.5 + 0.5·tanh(x·(a + b·x²)))`) so quantized output is bit-exact
against the C++ fused IS_ACT path. Uses `cute.math.tanh(fastmath=False)`
rather than the `tanh.approx.f32` PTX intrinsic — TE compiles activation
kernels without `--use_fast_math` by default, so its `tanhf` is the
IEEE-precise expansion."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This raises a question - we do actually have a knob to use fast math for activations - I assume that
there is no equivalent for that here? We should add that.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes I just found NVTE_BUILD_ACTIVATION_WITH_FAST_MATH. Fixed my code

def act_silu(x: Float32) -> Float32:
"""SiLU/Swish: x · σ(x) = x / (1 + e^-x).
Matches TE's `silu` (`val / (1 + expf(-val))`)."""
return x / (Float32(1.0) + cute.math.exp(-x, fastmath=True))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think expf (compiled without fast math) is the same as cute.math.exp(fastmath=True) - is it?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

"""Quick GELU: x · σ(1.702·x). Matches TE `qgelu_with_alpha(val, 1.702)` =
`cval · (1 / (1 + expf(-1.702·cval)))` (multiply by sigmoid, not a divide)."""
z = Float32(1.702) * x
return x * (Float32(1.0) / (Float32(1.0) + cute.math.exp(-z, fastmath=True)))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So why are we not reusing the sigmoid function here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah Claude Code wrote that. Refactored this

Comment on lines +44 to +70
std::string to_key() const {
std::string key;
key.reserve(56);
key.append("cutedsl_mxfp8_")
.append(te_dtype_to_str(dtype))
.append("_")
.append(te_dtype_to_str(fp8_dtype))
.append("_")
.append(rowwise ? "1" : "0")
.append("_")
.append(colwise ? "1" : "0")
.append("_")
.append(swizzled ? "1" : "0")
.append("_")
.append(with_amax ? "1" : "0")
.append("_")
.append(with_dbias ? "1" : "0")
.append("_")
.append(with_dact ? "1" : "0")
.append("_")
.append(with_act ? "1" : "0")
.append("_")
.append(with_noop ? "1" : "0")
.append("_")
.append(activation_to_str(activation));
return key;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of random, but this function is quite slow. You could do the same much faster with raw char*
manipulation.

@kainzhong kainzhong Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emmmm but I reserved 56 chars before I do append. I don't know if char* will be faster than this since they both don't require resizing the string?

Comment thread transformer_engine/common/cast/mxfp8/quantize_mxfp8_cutedsl.cuh
Comment thread transformer_engine/common/cast/mxfp8/quantize_mxfp8_cutedsl.cuh
Comment on lines +113 to +121
if(NOT TVM_FFI_CMAKE_QUERY EQUAL 0)
message(FATAL_ERROR
"Could not import the tvm_ffi Python package (with '${Python_EXECUTABLE}'), "
"which Transformer Engine requires to build the CuTeDSL quantize backend "
"bridge (common/tvm_ffi_bridge.h). Install it into this Python environment: "
"`pip install apache-tvm-ffi`.")
endif()
find_package(tvm_ffi CONFIG REQUIRED PATHS "${TVM_FFI_CMAKE_DIR}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 No opt-out CMake option for tvm_ffi dependency

The tvm_ffi detection is unconditional: if the package is absent the build hard-fails with FATAL_ERROR, with no NVTE_ENABLE_CUTEDSL CMake option to disable it. Every other optional feature in this file that has a build-time cost (NVTE_ENABLE_NVSHMEM, NVTE_WITH_CUBLASMP, etc.) is guarded by an option() flag. Without an analogous guard here, any environment where apache-tvm-ffi is not installed — CI images, embedded build systems, custom wheels — cannot build Transformer Engine at all, even if the CuTeDSL backend is never used at runtime.

@kainzhong
kainzhong force-pushed the cutedsl_mxfp8_common branch from 948fab5 to 2930b1b Compare July 10, 2026 00:34
Comment thread transformer_engine/common/CuTeDSL/utils_fp8.py
Comment thread transformer_engine/common/CuTeDSL/utils.py Outdated
Comment thread transformer_engine/common/__init__.py Outdated
Comment thread transformer_engine/common/CuTeDSL/utils.py
Comment thread transformer_engine/common/cast/mxfp8/quantize_mxfp8_cutedsl.cuh Outdated
Comment thread tests/pytorch/mxfp8/test_mxfp8_cutedsl_backend.py Outdated
Comment on lines +1 to +10
# Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# See LICENSE for license information.

"""Cross-backend bit-exactness tests for the CuTeDSL MXFP8 quantize kernels."""

import ctypes
import os
from typing import Callable, NamedTuple, Optional

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Unconditional top-level import tvm_ffi raises ImportError for users without the package

The test file imports tvm_ffi at module level before the pytestmark skip guard is evaluated. Pytest collects all test modules regardless of environment; users without apache-tvm-ffi installed will see a collection error instead of a clean skip. The import should be moved inside the test body or placed under a try/except ImportError guard that sets tvm_ffi_available = False, similar to how the test already conditionally sets cutedsl_enabled.

@kainzhong
kainzhong force-pushed the cutedsl_mxfp8_common branch from 6e55eef to c47fc5c Compare July 27, 2026 20:09
kainzhong and others added 4 commits July 27, 2026 20:09
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
for more information, see https://pre-commit.ci

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
kainzhong and others added 28 commits July 27, 2026 20:10
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
…it__.py

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
for more information, see https://pre-commit.ci

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
for more information, see https://pre-commit.ci

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
for more information, see https://pre-commit.ci

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
for more information, see https://pre-commit.ci

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
for more information, see https://pre-commit.ci

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Perform noop tensor check on device

Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
@kainzhong
kainzhong force-pushed the cutedsl_mxfp8_common branch from c47fc5c to 4815598 Compare July 27, 2026 20:10
Signed-off-by: Kaining Zhong <kainingz@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants