per-device capability probe: pre-Ada GPUs auto-fall back to upcast path
Browse files
libs/ltx_core/quantization/fp8_torch_mm.py
CHANGED
|
@@ -17,6 +17,22 @@ from ltx_core.quantization.fp8_cast import _replace_fwd_with_upcast
|
|
| 17 |
|
| 18 |
_F8_MAX = 448.0 # float8_e4m3fn finite max
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
def _replace_fwd_with_scaled_mm(layer: torch.nn.Linear) -> None:
|
| 22 |
"""Swap layer.forward for a runtime-branching fp8 path.
|
|
@@ -41,8 +57,9 @@ def _replace_fwd_with_scaled_mm(layer: torch.nn.Linear) -> None:
|
|
| 41 |
return layer.original_forward(*args, **_kwargs)
|
| 42 |
if layer.bias is not None and layer.bias.dtype == torch.float8_e4m3fn:
|
| 43 |
layer.bias.data = layer.bias.data.to(torch.bfloat16) # one-time restore
|
| 44 |
-
if (not (x.is_cuda and w.is_cuda)) or w.shape[0] % 16 or w.shape[1] % 16
|
| 45 |
-
|
|
|
|
| 46 |
w_up = w.to(x.dtype)
|
| 47 |
b = layer.bias.to(x.dtype) if layer.bias is not None else None
|
| 48 |
return torch.nn.functional.linear(x, w_up, b)
|
|
|
|
| 17 |
|
| 18 |
_F8_MAX = 448.0 # float8_e4m3fn finite max
|
| 19 |
|
| 20 |
+
_SM_OK: dict = {} # device -> bool: native fp8 mm available (sm_89+)
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def _scaled_mm_supported(device) -> bool:
|
| 24 |
+
ok = _SM_OK.get(device)
|
| 25 |
+
if ok is None:
|
| 26 |
+
try:
|
| 27 |
+
ok = torch.cuda.get_device_capability(device) >= (8, 9)
|
| 28 |
+
except Exception:
|
| 29 |
+
ok = False
|
| 30 |
+
_SM_OK[device] = ok
|
| 31 |
+
if not ok:
|
| 32 |
+
print(f"[ltx_core] fp8 scaled-mm: {device} lacks sm_89+ fp8 cores; "
|
| 33 |
+
"falling back to per-layer upcast on this device.", flush=True)
|
| 34 |
+
return ok
|
| 35 |
+
|
| 36 |
|
| 37 |
def _replace_fwd_with_scaled_mm(layer: torch.nn.Linear) -> None:
|
| 38 |
"""Swap layer.forward for a runtime-branching fp8 path.
|
|
|
|
| 57 |
return layer.original_forward(*args, **_kwargs)
|
| 58 |
if layer.bias is not None and layer.bias.dtype == torch.float8_e4m3fn:
|
| 59 |
layer.bias.data = layer.bias.data.to(torch.bfloat16) # one-time restore
|
| 60 |
+
if (not (x.is_cuda and w.is_cuda)) or w.shape[0] % 16 or w.shape[1] % 16 \
|
| 61 |
+
or not _scaled_mm_supported(x.device):
|
| 62 |
+
# CPU pass, non-16-aligned dims, or pre-Ada GPU: per-layer upcast math.
|
| 63 |
w_up = w.to(x.dtype)
|
| 64 |
b = layer.bias.to(x.dtype) if layer.bias is not None else None
|
| 65 |
return torch.nn.functional.linear(x, w_up, b)
|