# Metal

Metal 量化在 Apple Silicon（MPS）设备上使用托管于 Hugging Face Hub 的 Metal 内核（[kernels-community/mlx-quantization-metal-kernels](https://huggingface.co/kernels-community/mlx-quantization-metal-kernels)）执行仿射量化。这些内核源自 [MLX](https://github.com/ml-explore/mlx) 框架，并通过 [`kernels`](https://github.com/huggingface/kernels) 库进行编译。

权重被打包为带有分组缩放因子和偏置的 `uint32` 张量，前向传播使用融合的反量化 + 矩阵乘法 Metal 内核（`affine_qmm_t`）。这能在完全于 GPU 上运行推理且无需 CPU 往返的情况下，保持较低的内存占用。

支持的位宽为 **2、4 和 8**。分组大小可配置（默认值为 64）。

## 要求

- 支持 MPS 的 Apple Silicon Mac（M1 / M2 / M3 / M4）
- `kernels` 软件包：

```bash
pip install kernels
```

Metal 内核会在首次使用时从 Hub 自动下载——无需手动编译。

## 即时量化

通过传入 [MetalConfig](/docs/transformers/main/zh/main_classes/quantization#transformers.MetalConfig)，可以在加载时加载任意模型并对其进行量化。所有符合条件的 `nn.Linear` 层都会被替换为量化版本。

```python
from transformers import AutoModelForCausalLM, AutoTokenizer, MetalConfig

quantization_config = MetalConfig(bits=4, group_size=64)
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-1B",
    device_map="mps",
    quantization_config=quantization_config,
)

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-1B")
inputs = tokenizer("Apple Silicon is", return_tensors="pt").to("mps")
output = model.generate(**inputs, max_new_tokens=50)
print(tokenizer.decode(output[0], skip_special_tokens=True))
```

## 加载预量化模型

如果检查点中已经包含量化后的权重（`weight` 为打包的 uint32，`scales`、`qbiases`），则会直接加载它们，无需重新量化。

```python
from transformers import AutoModelForCausalLM, MetalConfig

model = AutoModelForCausalLM.from_pretrained(
    "your-org/model-metal-4bit",
    device_map="mps",
)
```

## 反量化

在没有 MPS 的机器上，预量化检查点会自动反量化回 float，以便模型仍可在 CPU 或 CUDA 上使用。您也可以显式强制此行为：

```python
from transformers import AutoModelForCausalLM, MetalConfig

config = MetalConfig(dequantize=True)
model = AutoModelForCausalLM.from_pretrained(
    "your-org/model-metal-4bit",
    quantization_config=config,
    device_map="cpu",
)
```

## 排除层

某些层（例如 `lm_head`）可以通过 `modules_to_not_convert` 从量化中排除：

```python
config = MetalConfig(bits=4, group_size=64, modules_to_not_convert=["lm_head"])
```

## 配置选项

| 参数 | 默认 | 描述 |
|---|---|---|
| `bits` | `4` | 用于权重量化的位宽（2、4 或 8） |
| `group_size` | `64` | 每个量化组的元素数量 |
| `modules_to_not_convert` | `None` | 需要以完整精度保留的模块名称列表 |
| `dequantize` | `False` | 强制反量化为 float（针对非 MPS 设备） |

