forked from MakazhanAlpamys/Soup
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfp8.py
More file actions
153 lines (117 loc) · 4.49 KB
/
Copy pathfp8.py
File metadata and controls
153 lines (117 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""FP8 training — 8-bit floating point training via torchao/transformer_engine.
FP8 training on Hopper (H100, H200) and Blackwell (B100, B200) GPUs uses 8-bit
floating point for matmuls, giving ~2x speedup vs bf16 at comparable quality.
This extends the existing int8-QAT infrastructure (``utils/qat.py``). When the
user sets ``quantization_aware: 'fp8'`` in soup.yaml the FP8 recipe is applied;
``quantization_aware: true`` keeps the legacy int8 QAT path.
Requires:
- NVIDIA Hopper+ GPU (SM 9.0+) — H100, H200, B100, B200
- torchao >= 0.5.0 OR transformer-engine >= 1.0
- CUDA 12.0+
"""
from __future__ import annotations
from typing import Literal, Union
QuantizationAwareLike = Union[bool, Literal["fp8"]]
def is_fp8_available() -> bool:
"""Return True if *any* FP8 training backend is importable.
Checks torchao's FP8 recipe first, then transformer-engine.
"""
# torchao path (preferred — we already require torchao for int8 QAT)
try:
from torchao.float8 import convert_to_float8_training # noqa: F401
return True
except ImportError:
pass
try:
import transformer_engine # noqa: F401
return True
except ImportError:
pass
return False
def is_fp8_gpu_supported() -> bool:
"""Return True if a Hopper+ GPU is detected (FP8 requires SM 9.0+)."""
try:
import torch
if not torch.cuda.is_available():
return False
# SM 9.0 = Hopper (H100), SM 10.0 = Blackwell (B100)
major, _ = torch.cuda.get_device_capability(0)
return major >= 9
except (ImportError, RuntimeError, AssertionError):
return False
def apply_fp8_training(
model,
recipe: str = "tensorwise",
) -> bool:
"""Convert eligible linear layers to FP8 for training.
Uses torchao's ``convert_to_float8_training`` with a scaling recipe
selected via :pydata:`Float8LinearConfig.from_recipe_name`.
Supported recipes (from ``torchao.float8.config.Float8LinearRecipeName``):
- ``"tensorwise"`` — single scale per tensor, cuBLAS kernel (fastest,
default, v0.28.0 behavior).
- ``"rowwise"`` — per-row scale, CUTLASS kernel, e4m3 everywhere,
power-of-2 scales (more accurate).
- ``"rowwise_with_gw_hp"`` — rowwise but grad_weight stays in high
precision (most accurate).
Args:
model: PyTorch model to convert (typically after LoRA has been applied).
recipe: Scaling recipe name. Default ``"tensorwise"``.
Returns:
True on success, False if FP8 is unavailable or conversion failed.
"""
if not is_fp8_available():
return False
try:
from torchao.float8 import convert_to_float8_training
from torchao.float8.config import Float8LinearConfig
config = Float8LinearConfig.from_recipe_name(recipe)
convert_to_float8_training(model, config=config)
return True
except (ImportError, RuntimeError, ValueError):
return False
def validate_fp8_config(
quantization_aware: QuantizationAwareLike,
backend: str,
device: str,
) -> list[str]:
"""Validate FP8 training config.
Args:
quantization_aware: TrainingConfig.quantization_aware (False/True/'fp8').
backend: Training backend (transformers/unsloth/mlx).
device: Training device (cuda/cpu/mps).
Returns:
List of error messages. Empty list means valid (or FP8 not requested).
"""
errors: list[str] = []
# Only validate when FP8 is explicitly requested
if quantization_aware != "fp8":
return errors
if backend == "unsloth":
errors.append(
"FP8 training is not compatible with the unsloth backend. "
"Unsloth uses its own fused kernels. Use backend: transformers."
)
return errors
if backend == "mlx":
errors.append(
"FP8 training is not supported on the mlx backend (Apple Silicon). "
"Use backend: transformers."
)
return errors
if device != "cuda":
errors.append(
"FP8 training requires CUDA. "
f"Current device: {device}."
)
return errors
if not is_fp8_gpu_supported():
errors.append(
"FP8 training requires a Hopper+ GPU (H100/H200/B100/B200, "
"compute capability >= 9.0)."
)
if not is_fp8_available():
errors.append(
"FP8 training dependencies are not installed. "
"Install with: pip install torchao (>=0.5.0)"
)
return errors