Skip to content

supports_int8_compute() disables native INT8 on MPS unconditionally — torch._int_mm has been implemented for MPS since Aug 14 2026 #16458

Description

@designis1gt-alt

Summary

comfy/model_management.py::supports_int8_compute() returns False for MPS
unconditionally. The inline comment states that PyTorch does not implement
torch._int_mm for MPS and links pytorch/pytorch#141287.

That premise is out of date. Native _int_mm for MPS landed in PyTorch on
2026-08-14 (PR pytorch/pytorch#193153, commit 65366750d9, "[MPS] Add native
_int_mm support"). On a current nightly it works and is bit-exact against CPU.

The commit that introduced the gate — 313a76fb (#16130) — is titled "Disable
int8 weight-only quantization on devices without torch._int_mm"
, but the
implementation disables it on all MPS devices without probing the capability.

Effect

On macOS 26 + PyTorch nightly ≥ 2.15.0.dev20260815, every INT8 path silently
falls back to emulation. There is no error and no warning — only the model-load
line changes:

Before (ComfyUI 0.33.1):

Native ops: convrot_w4a4, int8_tensorwise, asym_w4a8_int8 , emulated ops: nvfp4, mxfp8, float8_e4m3fn, float8_e5m2

After (ComfyUI 0.37.0):

Native ops: , emulated ops: convrot_w4a4, mxfp8, int8_tensorwise, nvfp4, float8_e4m3fn, float8_e5m2, asym_w4a8_int8

Measured on a MacBook Pro 16" M5 Pro, 48 GB unified, macOS 26.6.2, with
torch 2.15.0.dev20260816 + torchvision 0.30.0.dev20260816, started with
env -u PYTORCH_ENABLE_MPS_FALLBACK, reference workflow Z-Image Turbo INT8
(z_image_turbo_int8_convrot.safetensors), 1024x1024, 8 steps,
res_multistep/simple, cfg 1.0, warm runs only:

Build | Warmed reference time | Native ops -- | -- | -- 0.33.1 | 30.09 s | three ops 0.37.0, unpatched | 32.09 s (+6.6%) | none 0.37.0 + patch below | 30.08 s | three ops

Verification that _int_mm really works on MPS here

python
import torch
for M, K, N in [(64,128,64), (256,512,256), (1024,1024,1024)]:
    a = torch.randint(-128, 127, (M, K), dtype=torch.int8)
    b = torch.randint(-128, 127, (K, N), dtype=torch.int8)
    assert torch.equal(torch._int_mm(a, b), torch._int_mm(a.to("mps"), b.to("mps")).cpu())
print("bit-exact on all three sizes")

All three pass on the configuration above.

Suggested fix

Probe the capability instead of denying by device type — this matches the stated
intent of #16130 and keeps the crash fix for builds where _int_mm is genuinely
missing:

python
_MPS_INT_MM_WORKS = None

def _mps_int_mm_works():
global _MPS_INT_MM_WORKS
if _MPS_INT_MM_WORKS is None:
try:
a = torch.randint(-8, 8, (32, 32), dtype=torch.int8, device="mps")
b = torch.randint(-8, 8, (32, 32), dtype=torch.int8, device="mps")
torch._int_mm(a, b)
_MPS_INT_MM_WORKS = True
except Exception:
_MPS_INT_MM_WORKS = False
return _MPS_INT_MM_WORKS

def supports_int8_compute(device=None):
if (device is not None and is_device_mps(device)) or mps_mode():
return _mps_int_mm_works()
...

Happy to open a PR if that shape is acceptable.

Environment

  • ComfyUI 0.37.0 (73c9bad4)
  • macOS 26.6.2 (build 25G83), MacBook Pro 16" M5 Pro, 48 GB unified
  • Python 3.12.13, torch 2.15.0.dev20260816, torchvision 0.30.0.dev20260816
  • comfy-kitchen 0.2.35, comfy-aimdo 0.5.5
  • Launched with env -u PYTORCH_ENABLE_MPS_FALLBACK python main.py --use-pytorch-cross-attention

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions