Skip to content

Commit f4b03e9

Browse files
committed
Merge branch 'develop/v1-2-0' into export/v1-2-0
2 parents e6d8050 + 16f3d09 commit f4b03e9

29 files changed

Lines changed: 671 additions & 68 deletions

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
- `create_inference_layer()` builds `OneBitLinear` via `OneBitLinear.from_quantization_result()`
2323
- Added `_build_quantization_bits()` static method for per-layer metadata
2424

25+
### Apple Silicon / macOS support
26+
27+
- **MPS quantization**: GPTQ (and AutoBit with GPTQ-only candidates) on `device="mps"`; cross-platform `empty_cache()` via new `onecomp/utils/device.py` (`runner.py`, `quantizer/gptq/_gptq.py`, `quantizer/_quantizer.py`)
28+
- **MPS device placement (GPTQ on CPU, QEP correction on MPS)**: With `device="mps"`, `run_gptq` moves the Hessian and weights to **CPU** for the full column-wise GPTQ loop (including inverse-Hessian Cholesky). The main reason is not absent Cholesky kernels on MPS (recent PyTorch supports them); if the GPTQ loop stayed on MPS, `maxq.item()` inside `quantize()` would run once per column—each call waits for pending MPS work to finish and read back a single scalar to the host (per-column host sync), not a full matrix copy per column—and that overhead is often several times slower than CPU on Apple Silicon (~4× in internal benchmarks with PyTorch 2.12). When QEP weight correction runs (`adjust_weight`, typically under `qep=True`), per-layer work stays on **MPS** (e.g. `weight @ delta_hatX`); only the Cholesky solve uses CPU via `_safe_cholesky_and_solve` (one solve per layer). A full CPU fallback for QEP does not materially improve speed. Calibration forwards may still use MPS. Details: README (macOS / MPS).
29+
- **MPS inference**: load saved quantized models on Mac with `QuantizedModelLoader` + Transformers `generate()` (GemLite/vLLM remain Linux + CUDA)
30+
- **macOS `uv sync`**: added `darwin` to `tool.uv.environments`, `--extra mps` for MPS-enabled PyTorch from PyPI; `--extra cpu` is Linux-only (pytorch-cpu index); Linux-only markers on CUDA extras (`cu118``cu130`)
31+
2532
## New Feature : Dashboard
2633

2734
- Added `dashboard/`, a browser-based web app for OneCompression on **SLURM-managed HPC GPU nodes without Docker**: pick a Hugging Face model and quantization settings in the UI, run jobs on the GPU, deploy the quantized checkpoint, and validate inference via chat

README.md

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,30 @@ import torch
100100
print(torch.cuda.is_available())
101101
```
102102

103+
#### ✅ macOS (MPS)
104+
105+
On macOS, install PyTorch from PyPI (default wheels include MPS support). You do **not** need the CUDA index URLs above.
106+
107+
```bash
108+
pip install torch torchvision torchaudio
109+
```
110+
111+
Verify MPS:
112+
```python
113+
import torch
114+
print(torch.backends.mps.is_available())
115+
```
116+
117+
Then install OneComp from PyPI (see step 2 below). GPTQ quantization and Hugging Face `generate()` inference on MPS are supported; vLLM serving requires Linux with an NVIDIA GPU. An editable install from a git clone is **not** required for MPS use — see [for developers (pip)](#for-developers-pip) only if you are contributing to OneComp.
118+
119+
> **MPS device placement (GPTQ vs QEP)**
120+
> With `device="mps"`, calibration and model forward passes can run on the GPU. The bottleneck is usually not missing Cholesky ops on MPS (recent PyTorch builds implement them); the implementation splits work as follows:
121+
>
122+
> - GPTQ (`run_gptq`): Hessian and weights are moved to CPU for the full column-wise loop (including inverse-Hessian Cholesky). If that loop stayed on MPS, `quantize()` would call `maxq.item()` once per column; each call triggers **per-column host sync** (wait for pending MPS ops, then read one scalar—not a full Hessian/weight copy every column)—often several times slower than CPU on Apple Silicon (e.g. ~4× in internal benchmarks with PyTorch 2.12). Keeping GPTQ on CPU avoids that overhead. With `mse=True`, `find_params` also calls `quantize()` in a grid loop and benefits from the same CPU placement.
123+
> - QEP weight correction (`adjust_weight`, when QEP correction runs—typically `qep=True` with error propagation enabled): Per-layer work stays on MPS (e.g. `weight @ delta_hatX`, diagonal damping). Only the Cholesky solve uses CPU via `_safe_cholesky_and_solve` (one solve per layer, not per column); moving all of QEP to CPU does not materially improve speed. The subsequent GPTQ step still uses the CPU path above.
124+
>
125+
> DBF-based AutoBit fallback and multi-GPU quantization are not supported on MPS.
126+
103127
#### 2. Install `onecomp`
104128

105129
Once PyTorch is installed, you can install `onecomp`:
@@ -128,27 +152,42 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
128152

129153
git clone https://github.com/FujitsuResearch/OneCompression.git
130154
cd OneCompression
131-
uv sync --extra cu128 --extra dev --extra visualize
132155
```
133156

134157
The `uv sync` command creates a Python virtual environment and installs all dependent libraries.
135158

159+
#### Linux (CUDA quantization / vLLM)
160+
161+
```bash
162+
uv sync --extra cu128 --extra dev --extra visualize
163+
```
164+
136165
The `--extra cu128` option installs the CUDA-enabled version of PyTorch (along with `torchvision` from the same CUDA index).
137166
Replace `cu128` with the appropriate variant for your environment: `cpu`, `cu118`, `cu121`, `cu124`, `cu126`, `cu128`, or `cu130`.
138167
PyTorch will be automatically downloaded by `uv`, so you do not need to install it beforehand.
139168

169+
#### macOS (development / MPS inference)
170+
171+
```bash
172+
uv sync --extra mps --extra dev --extra visualize
173+
```
174+
175+
On macOS, use `--extra mps` only. CUDA extras (`cu118``cu130`), `--extra cpu` (Linux-only), and `--extra vllm` are not supported on macOS.
176+
After `uv sync`, you can run GPTQ quantization and Hugging Face `generate()` inference on MPS; vLLM serving still requires Linux with an NVIDIA GPU.
177+
See the **MPS device placement (GPTQ vs QEP)** note under [macOS (MPS)](#macos-mps) above for why GPTQ runs on CPU while QEP correction uses MPS.
178+
140179
Adding `--extra dev` installs development tools (black, pre-commit, pytest, pylint).
141180
Adding `--extra visualize` installs matplotlib for visualization features.
142181
Adding `--extra distributed` installs DeepSpeed for multi-GPU training.
143182
Adding `--extra hydra` installs `hydra-core` for the example scripts and `model_validation/` runners that use Hydra-based configuration.
144183

145-
To use vLLM for serving quantized models, add `--extra vllm` together with `--extra cu130`:
184+
To use vLLM for serving quantized models on Linux, add `--extra vllm` together with `--extra cu130`:
146185

147186
```bash
148187
uv sync --extra cu130 --extra dev --extra visualize --extra vllm
149188
```
150189

151-
> **Note:** `--extra vllm` is only compatible with `--extra cu130`. Recent vLLM releases require `torch>=2.10`, whose wheels are only published for the `cu130` index. Combining `--extra vllm` with `cpu` / `cu118` / `cu121` / `cu124` / `cu126` / `cu128` is rejected by `uv` at lock time.
190+
> **Note:** `--extra vllm` is only compatible with `--extra cu130`. Recent vLLM releases require `torch>=2.10`, whose wheels are only published for the `cu130` index. Combining `--extra vllm` with `cpu` / `mps` / `cu118` / `cu121` / `cu124` / `cu126` / `cu128` is rejected by `uv` at lock time.
152191
153192
> **Note:** `--extra vllm` may take a long time on the first run if a pre-built `xformers` wheel is not available for your Python/CUDA combination (e.g. Python 3.13). Using Python 3.12 typically avoids this.
154193
@@ -175,6 +214,8 @@ black --check onecomp/
175214

176215
### for developers (pip)
177216

217+
> **Note:** The editable install below is for developing OneComp from a local clone. **macOS users who only want MPS inference or quantization should use the [for users (pip)](#for-users-pip) flow** (`pip install torch` then `pip install onecomp` from PyPI); `pip install -e` is not needed for MPS.
218+
178219
```bash
179220
git clone <git repository URL>
180221
cd OneCompression
@@ -224,8 +265,10 @@ uv run pre-commit run --all-files
224265

225266
### Building Documentation Locally
226267

268+
`--extra docs` alone is sufficient (no PyTorch `mps` / `cu*` extra required):
269+
227270
```bash
228-
uv sync --extra cu128 --extra dev --extra docs
271+
uv sync --extra docs
229272
uv run mkdocs serve
230273
```
231274

docs/api/quantized_model_loader.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
Loader for quantized models saved by OneComp.
44

5+
On macOS, `load_quantized_model()` places the model on MPS when available
6+
(CUDA > MPS > CPU via `get_default_device()`). Use Transformers `generate()` for
7+
inference; vLLM requires Linux with an NVIDIA GPU. See the
8+
[macOS / MPS guide](../user-guide/mps.md#inference-with-transformers).
9+
510
::: onecomp.quantized_model_loader.QuantizedModelLoader
611
options:
712
show_source: false

docs/getting-started/installation.md

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ This page describes how to install Fujitsu One Compression (OneComp).
55
## Requirements
66

77
- Python 3.12 or later (< 3.14)
8-
- PyTorch (CPU or CUDA)
8+
- PyTorch (CPU, CUDA, or MPS on macOS)
99

1010
## For Users (pip)
1111

@@ -55,15 +55,40 @@ Install the appropriate version of PyTorch for your system.
5555
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu130
5656
```
5757

58-
Check your CUDA version:
58+
=== "macOS (MPS)"
59+
60+
On macOS, install PyTorch from PyPI (default wheels include MPS support).
61+
You do **not** need the CUDA index URLs above.
62+
63+
```bash
64+
pip install torch torchvision torchaudio
65+
```
66+
67+
Verify MPS:
68+
69+
```python
70+
import torch
71+
print(torch.backends.mps.is_available())
72+
```
73+
74+
Then install OneComp (step 2 below). GPTQ quantization and Hugging Face
75+
`generate()` inference on MPS are supported; vLLM serving requires Linux with
76+
an NVIDIA GPU. An editable install from a git clone is **not** required for
77+
MPS use — see [For Developers (pip)](#for-developers-pip) only if you are
78+
contributing to OneComp.
79+
80+
For usage (`device="mps"`, VRAM budget, limitations), see the
81+
[macOS / MPS guide](../user-guide/mps.md).
82+
83+
Check your CUDA version (Linux / Windows with NVIDIA GPU):
5984

6085
```bash
6186
nvcc --version
6287
# or
6388
nvidia-smi
6489
```
6590

66-
Verify PyTorch GPU support:
91+
Verify PyTorch GPU support (CUDA):
6792

6893
```python
6994
import torch
@@ -97,27 +122,46 @@ It provides deterministic, reproducible environments via its lockfile.
97122
# Install uv (macOS or Linux)
98123
curl -LsSf https://astral.sh/uv/install.sh | sh
99124

100-
# Clone and set up
101125
git clone https://github.com/FujitsuResearch/OneCompression.git
102126
cd OneCompression
127+
```
128+
129+
The `uv sync` command creates a virtual environment and installs all dependencies.
130+
131+
### Linux (CUDA quantization / vLLM)
132+
133+
```bash
103134
uv sync --extra cu128 --extra dev --extra visualize
104135
```
105136

106-
The `uv sync` command creates a virtual environment and installs all dependencies (including `torchvision` from the same CUDA index as PyTorch).
107-
Replace `cu128` with the appropriate CUDA variant for your system: `cpu`, `cu118`, `cu121`, `cu124`, `cu126`, `cu128`, or `cu130`.
137+
The `--extra cu128` option installs the CUDA-enabled version of PyTorch (along with `torchvision` from the same CUDA index).
138+
Replace `cu128` with the appropriate variant for your environment: `cpu`, `cu118`, `cu121`, `cu124`, `cu126`, `cu128`, or `cu130`.
139+
PyTorch will be automatically downloaded by `uv`, so you do not need to install it beforehand.
140+
141+
### macOS (development / MPS inference)
142+
143+
```bash
144+
uv sync --extra mps --extra dev --extra visualize
145+
```
146+
147+
On macOS, use `--extra mps` only. CUDA extras (`cu118``cu130`), `--extra cpu` (Linux-only),
148+
and `--extra vllm` are not supported on macOS.
149+
After `uv sync`, you can run GPTQ quantization and Hugging Face `generate()` inference on MPS;
150+
vLLM serving still requires Linux with an NVIDIA GPU.
151+
See the [macOS / MPS guide](../user-guide/mps.md) for device placement and usage details.
108152

109153
Adding `--extra dev` installs development tools (black, pytest, pylint).
110154
Adding `--extra visualize` installs matplotlib for visualization features.
111155
Adding `--extra distributed` installs DeepSpeed for multi-GPU training.
112156

113-
To use vLLM for serving quantized models, add `--extra vllm` together with `--extra cu130`:
157+
To use vLLM for serving quantized models on Linux, add `--extra vllm` together with `--extra cu130`:
114158

115159
```bash
116160
uv sync --extra cu130 --extra dev --extra visualize --extra vllm
117161
```
118162

119163
!!! note "vLLM requires the `cu130` extra"
120-
Recent vLLM releases depend on `torch>=2.10`, whose wheels are only published for the `cu130` index. The `--extra vllm` declaration in `pyproject.toml` therefore conflicts with `cpu`, `cu118`, `cu121`, `cu124`, `cu126`, and `cu128`; combining any of these with `--extra vllm` is rejected by `uv` at lock time.
164+
Recent vLLM releases depend on `torch>=2.10`, whose wheels are only published for the `cu130` index. The `--extra vllm` declaration in `pyproject.toml` therefore conflicts with `cpu`, `mps`, `cu118`, `cu121`, `cu124`, `cu126`, and `cu128`; combining any of these with `--extra vllm` is rejected by `uv` at lock time.
121165

122166
!!! warning "vLLM 0.22+ is not supported"
123167
vLLM 0.22.0 removed the legacy Exllama GPTQ kernel that OneComp's GPTQ serving relies on for low bit-widths (2-/3-bit, and Marlin-ineligible 4-/8-bit), so `pyproject.toml` pins `vllm>=0.10,<0.22`. See [vLLM Inference](../user-guide/vllm-inference.md#installation) for details.
@@ -148,19 +192,30 @@ uv sync --extra cu130 --extra dev --extra visualize --extra vllm
148192

149193
## For Developers (pip)
150194

195+
!!! note
196+
The editable install below is for developing OneComp from a local clone.
197+
**macOS users who only want MPS inference or quantization should use the
198+
[For Users (pip)](#for-users-pip) flow** (`pip install torch` then
199+
`pip install onecomp` from PyPI); `pip install -e` is not needed for MPS.
200+
151201
```bash
152202
git clone https://github.com/FujitsuResearch/OneCompression.git
153203
cd OneCompression
154204

155-
# Install PyTorch with CUDA support
205+
# First, install PyTorch for your environment
156206
pip install torch --index-url https://download.pytorch.org/whl/cu128
157-
158-
# Install onecomp with development dependencies
207+
# Then install onecomp with development dependencies
159208
pip install -e ".[dev]"
160209
```
161210

211+
Replace `cu128` with the appropriate variant for your environment: `cpu`, `cu118`, `cu121`, `cu124`, `cu126`, `cu128`, or `cu130`.
212+
On macOS, install PyTorch from PyPI instead (see [macOS (MPS)](#step-1-install-pytorch) above).
213+
162214
## Building Documentation Locally
163215

216+
`--extra docs` alone is enough. PyTorch extras (`mps`, `cu*`, `cpu`) are not required
217+
to build or serve the documentation.
218+
164219
```bash
165220
uv sync --extra docs
166221
uv run mkdocs serve

docs/getting-started/quickstart.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ quantized model is saved to `TinyLlama-1.1B-...-autobit-<X>bit/` by default.
3131
|------------------------|------------|----------------------------------------------------------|
3232
| `model_id` | (required) | Hugging Face model ID or local path |
3333
| `wbits` | `None` | Target bitwidth. When `None`, estimated from VRAM |
34-
| `total_vram_gb` | `None` | VRAM budget in GB. When `None`, detected from GPU |
34+
| `total_vram_gb` | `None` | VRAM budget in GB. When `None`, detected from CUDA GPU |
3535
| `groupsize` | `128` | GPTQ group size (`-1` to disable) |
36-
| `device` | `"cuda:0"` | Device for computation |
36+
| `device` | `"cuda:0"` | Device for computation (`"mps"` on macOS — see below) |
3737
| `qep` | `True` | Enable QEP (Quantization Error Propagation) |
3838
| `evaluate` | `True` | Calculate perplexity and zero-shot accuracy |
3939
| `eval_original_model` | `False` | Also evaluate the original (unquantized) model |
@@ -66,6 +66,21 @@ Runner.auto_run(
6666
)
6767
```
6868

69+
### macOS (Apple Silicon)
70+
71+
On Mac, set `device="mps"` and pass `total_vram_gb` (VRAM auto-detection uses CUDA only):
72+
73+
74+
```python
75+
Runner.auto_run(
76+
model_id="TinyLlama/TinyLlama-1.1B-intermediate-step-1431k-3T",
77+
device="mps",
78+
total_vram_gb=16,
79+
)
80+
```
81+
See the [macOS / MPS guide](../user-guide/mps.md) for supported features, device
82+
placement (GPTQ vs QEP), and inference with Transformers.
83+
6984
---
7085

7186
## Step-by-step Workflow
@@ -178,3 +193,4 @@ model, tokenizer = load_quantized_model("./output/quantized_model")
178193
- [Examples](../user-guide/examples.md) -- more usage patterns including multi-GPU and chunked calibration
179194
- [Evaluation](../user-guide/evaluation.md) -- `onecomp-eval` for MT-Bench and throughput on vLLM-served models
180195
- [Algorithms](../algorithms/overview.md) -- learn about the quantization algorithms available in OneComp
196+
- [macOS / MPS](../user-guide/mps.md) -- Apple Silicon setup, limitations, and inference

docs/user-guide/basic-usage.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,15 @@ model_config = ModelConfig(
6060
| `model_id` | Hugging Face Hub model ID ||
6161
| `path` | Local path to a saved model ||
6262
| `dtype` | Data type (`"float16"`, `"float32"`)| `"float16"` |
63-
| `device` | Device (`"cpu"`, `"cuda"`, `"auto"`)| `"auto"` |
63+
| `device` | Device (`"cpu"`, `"cuda"`, `"mps"`, `"auto"`)| `"auto"` |
6464

6565
You must provide either `model_id` or `path`.
6666

67+
!!! tip "macOS (Apple Silicon)"
68+
Use `device="mps"` for quantization on Mac. `Runner.auto_run` defaults to
69+
`cuda:0`; pass `device="mps"` and `total_vram_gb` explicitly. See the
70+
[macOS / MPS guide](mps.md).
71+
6772
## Step 2: Choose a Quantizer
6873

6974
```python

docs/user-guide/cli.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ onecomp [-h] [--wbits WBITS] [--total-vram-gb GB] [--groupsize GROUPSIZE]
4343
| Option | Default | Description |
4444
|---------------------------|--------------|----------------------------------------------------------|
4545
| `--wbits WBITS` | `None` (auto)| Target bitwidth. When omitted, estimated from VRAM |
46-
| `--total-vram-gb GB` | `None` (auto)| VRAM budget in GB for bitwidth estimation. When omitted, detected from GPU |
46+
| `--total-vram-gb GB` | `None` (auto)| VRAM budget in GB for bitwidth estimation. When omitted, detected from CUDA GPU. **Required on MPS** when `--wbits` is omitted |
4747
| `--groupsize GROUPSIZE` | `128` | GPTQ group size (`-1` to disable grouping) |
48-
| `--device DEVICE` | `cuda:0` | Device to place the model on |
48+
| `--device DEVICE` | `cuda:0` | Device to place the model on (`mps` on macOS) |
4949
| `--no-qep` | | Disable QEP (enabled by default) |
5050
| `--no-eval` | | Skip perplexity and accuracy evaluation |
5151
| `--eval-original` | | Also evaluate the original (unquantized) model |
@@ -122,6 +122,8 @@ onecomp meta-llama/Llama-2-7b-hf --eval-original
122122
onecomp meta-llama/Llama-2-7b-hf --device cuda:1
123123
```
124124

125+
See the [macOS / MPS guide](mps.md) for supported quantizers and limitations.
126+
125127
## Default Behavior
126128

127129
When run with no options, the `onecomp` command:

0 commit comments

Comments
 (0)