Skip to content

Commit f17384f

Browse files
authored
Merge branch 'main' into fix/graph-root-module-weight
2 parents b458fd2 + 3f5b05d commit f17384f

16 files changed

Lines changed: 418 additions & 236 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,23 @@ jobs:
3838
run: make check
3939

4040
test-smoke:
41-
name: Linux / make test-smoke
41+
name: Linux / make test-smoke / torch=${{ matrix.torch_version }}
4242
runs-on: ubuntu-latest
4343
timeout-minutes: 60
4444
env:
4545
INSTALL_PRECOMMIT: "false"
46+
strategy:
47+
fail-fast: false
48+
matrix:
49+
include:
50+
- torch_group: torch_2_8
51+
torch_version: "2.8"
52+
- torch_group: torch_2_9
53+
torch_version: "2.9"
54+
- torch_group: torch_2_10
55+
torch_version: "2.10"
56+
- torch_group: torch_2_11
57+
torch_version: "2.11"
4658
steps:
4759
- name: Check out repository
4860
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
@@ -51,7 +63,7 @@ jobs:
5163
with:
5264
enable-cache: false
5365
- name: Run `make test-smoke`
54-
run: make test-smoke
66+
run: make test-smoke TORCH_GROUP=${{ matrix.torch_group }}
5567

5668
test-tutorials:
5769
name: Linux / make test-tutorials

Makefile

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Use of this source code is governed by a BSD-3-Clause license that can
44
# be found in the LICENSE file or at https://opensource.org/licenses/BSD-3-Clause
55

6-
.PHONY: _maybe_patch_pyproject all api-list build check clean distclean distclean-all docs docs-clean docs-open env env-all env-docs env-highest-torch env-tutorial render-api-index set-auto-venv test test-cov test-fast test-highest-pytorch test-lowest-pytorch test-slow test-smoke test-tutorials version
6+
.PHONY: _maybe_patch_pyproject all api-list build check clean distclean distclean-all docs docs-clean docs-open env env-all env-docs env-highest-torch env-lowest-torch env-tutorial render-api-index set-auto-venv test test-cov test-fast test-highest-pytorch test-lowest-pytorch test-slow test-smoke test-tutorials version
77

88
SHELL := /bin/bash
99

@@ -53,6 +53,17 @@ VENV_HIGHEST_TORCH ?= .venv-highest-torch
5353
VENV_LOWEST_TORCH ?= .venv-lowest-torch
5454
VENV_TUTORIAL ?= .venv-tutorial
5555

56+
# The torch_2_* groups (pyproject.toml [dependency-groups]) currently at
57+
# each end of the supported range. Bump these two lines — nothing else —
58+
# when the project's torch version bounds change.
59+
HIGHEST_TORCH_GROUP := torch_2_11
60+
LOWEST_TORCH_GROUP := torch_2_8
61+
62+
# Torch dependency group (pyproject.toml [dependency-groups]) that every
63+
# environment-building target (env, test, test-smoke, docs, ...) pins to.
64+
TORCH_GROUP ?= $(HIGHEST_TORCH_GROUP)
65+
export TORCH_GROUP
66+
5667
# Documentation directory. Defaults to $(MAKEFILE_DIR)docs so the same recipe
5768
# works in both contexts:
5869
#
@@ -176,9 +187,14 @@ env: _maybe_patch_pyproject
176187

177188
# Set up development environment with latest supported PyTorch version
178189
env-highest-torch: _maybe_patch_pyproject
179-
@$(SETUP_ENV) --venv $(VENV_HIGHEST_TORCH) --python-version $(PYTHON_VERSION) --with-highest_tested_torch
190+
@TORCH_GROUP=$(HIGHEST_TORCH_GROUP) $(SETUP_ENV) --venv $(VENV_HIGHEST_TORCH) --python-version $(PYTHON_VERSION)
180191
@$(call write_active_venv,$(VENV_HIGHEST_TORCH))
181192

193+
# Set up development environment with lowest supported PyTorch version
194+
env-lowest-torch: _maybe_patch_pyproject
195+
@TORCH_GROUP=$(LOWEST_TORCH_GROUP) $(SETUP_ENV) --venv $(VENV_LOWEST_TORCH) --python-version $(PYTHON_VERSION)
196+
@$(call write_active_venv,$(VENV_LOWEST_TORCH))
197+
182198
# Set up environment for running tutorials (quantization notebook)
183199
env-tutorial: _maybe_patch_pyproject
184200
@$(SETUP_ENV) --venv $(VENV_TUTORIAL) --python-version $(PYTHON_VERSION) --with-tutorial
@@ -235,29 +251,30 @@ test-slow:
235251
@$(MAKE) test PYTEST_ARGS="--marker slow"
236252

237253
# Run smoke tests only (pass PYTEST_ARGS for custom flags, e.g., make test-smoke PYTEST_ARGS="--junitxml=results.xml").
254+
# Pass TORCH_GROUP to smoke test against a specific torch version (default: HIGHEST_TORCH_GROUP).
238255
test-smoke:
239256
@$(call use_env,VENV) && \
240257
echo "Running smoke tests..." && \
241258
uv run --no-sync --active nox -f $(MAKEFILE_DIR)ci/nox/noxfile.py -s smoke_tests -- $(PYTEST_ARGS) && \
242259
echo "All smoke tests passed!"
243260

244261
# Run tests on lowest supported PyTorch version (pass PYTEST_ARGS for custom flags)
245-
test-lowest-pytorch:
262+
test-lowest-pytorch: env-lowest-torch
246263
@echo "Running tests on lowest PyTorch version supported..."
247-
@$(call use_env,VENV_LOWEST_TORCH,--with-lowest_tested_torch) && \
248-
echo "Testing with lowest supported PyTorch versions" && \
249-
uv run --no-sync --active python $(SCRIPTS)/make/log_versions.py && \
250-
$(RUN_TESTS) $(PYTEST_ARGS) && \
251-
echo "All tests passed!"
264+
@source $(VENV_LOWEST_TORCH)/bin/activate && \
265+
echo "Testing with lowest supported PyTorch versions" && \
266+
uv run --no-sync --active python $(SCRIPTS)/make/log_versions.py && \
267+
$(RUN_TESTS) $(PYTEST_ARGS) && \
268+
echo "All tests passed!"
252269

253270
# Run tests on highest supported PyTorch version (pass PYTEST_ARGS for custom flags)
254-
test-highest-pytorch:
271+
test-highest-pytorch: env-highest-torch
255272
@echo "Running tests on highest PyTorch version supported..."
256-
@$(call use_env,VENV_HIGHEST_TORCH,--with-highest_tested_torch) && \
257-
echo "Testing with latest supported PyTorch versions" && \
258-
uv run --no-sync --active python $(SCRIPTS)/make/log_versions.py && \
259-
$(RUN_TESTS) $(PYTEST_ARGS) && \
260-
echo "All tests passed!"
273+
@source $(VENV_HIGHEST_TORCH)/bin/activate && \
274+
echo "Testing with latest supported PyTorch versions" && \
275+
uv run --no-sync --active python $(SCRIPTS)/make/log_versions.py && \
276+
$(RUN_TESTS) $(PYTEST_ARGS) && \
277+
echo "All tests passed!"
261278

262279
# Run tutorial notebook tests
263280
test-tutorials:

changelog.d/42.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Reject per-channel activation quantization on CoreML export

ci/nox/noxfile.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,14 @@
3434
options.default_venv_backend = "uv"
3535
options.error_on_missing_interpreters = True
3636

37+
TORCH_GROUP = os.environ.get("TORCH_GROUP")
3738

38-
@session(python=get_supported_python_versions(), uv_extras=["coreai"], uv_groups=["test"])
39+
40+
@session(
41+
python=get_supported_python_versions(),
42+
uv_extras=["coreai"],
43+
uv_groups=["test", TORCH_GROUP],
44+
)
3945
def smoke_tests(session: Session) -> None:
4046
"""Smoke test the package build and coreai_opt imports and basic functionality.
4147

pyproject.toml

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ dependencies = [
4646
# based on other package versions. We can either 1) add a stricter check to require the newer torchao
4747
# version for everyone, or 2) add a runtime check in src/coreai_opt/init.py to ensure torchao
4848
# version >= 0.15.0 for torch version >= 2.9.0. Opting option 1.
49-
# These torch versions must be in bounds of lowest_tested_torch and highest_tested_torch
49+
# These torch versions must be in bounds of torch_2_8, torch_2_9, torch_2_10, and torch_2_11
5050
"torch>=2.8.0,<=2.11.0",
5151
"torchao>=0.15.0,<=0.17.0",
5252
"tqdm>=4.65",
@@ -107,20 +107,6 @@ docs = [
107107
# This applies to the `coreml` group as well.
108108
coreai = [ "coreai-opt[coreai]" ]
109109
coreml = [ "coreai-opt[coreml]" ]
110-
# Used in CI to force latest mimimum supported torch version
111-
# These torch versions must be in bounds of torch versions listed in project dependencies
112-
highest_tested_torch = [
113-
"torch==2.11.0",
114-
"torchao==0.17.0",
115-
"torchvision==0.26.0",
116-
]
117-
# Used in CI to force lowest mimimum supported torch version
118-
# These torch versions must be in bounds of torch versions listed in project dependencies
119-
lowest_tested_torch = [
120-
"torch==2.8.0",
121-
"torchao==0.15.0",
122-
"torchvision==0.23.0",
123-
]
124110
pre-commit = [
125111
"bashate>=2.1.1",
126112
"darker>=3.0.0",
@@ -144,6 +130,27 @@ pre-commit = [
144130
"tomli-w>=1.0.0",
145131
]
146132
tamm-export = []
133+
# These torch versions must be in bounds of torch versions listed in project dependencies
134+
torch_2_10 = [
135+
"torch==2.10.0",
136+
"torchao==0.16.0",
137+
"torchvision==0.25.0",
138+
]
139+
torch_2_11 = [
140+
"torch==2.11.0",
141+
"torchao==0.17.0",
142+
"torchvision==0.26.0",
143+
]
144+
torch_2_8 = [
145+
"torch==2.8.0",
146+
"torchao==0.15.0",
147+
"torchvision==0.23.0",
148+
]
149+
torch_2_9 = [
150+
"torch==2.9.1",
151+
"torchao==0.15.0",
152+
"torchvision==0.24.1",
153+
]
147154
# Since torch and torchao are project dependencies, we need to include torchvision in dev
148155
# This allows standard `make test` to find torchvision
149156
torchvision = [
@@ -190,8 +197,10 @@ exclude-newer-package = { coreai-core = false, coreai-torch = false }
190197
# Declare conflicting groups so uv does not error
191198
conflicts = [
192199
[
193-
{ group = "highest_tested_torch" },
194-
{ group = "lowest_tested_torch" },
200+
{ group = "torch_2_8" },
201+
{ group = "torch_2_9" },
202+
{ group = "torch_2_10" },
203+
{ group = "torch_2_11" },
195204
],
196205
]
197206
[tool.uv.sources]

scripts/make/setup_env.sh

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ fi
5959
# - in_section && /^\[/: If we're in the section AND hit another section header (line starting with [)
6060
# * exit: Stop processing (we've left the dependency-groups section)
6161
# - in_section {print}: If we're in the section, print the line
62-
# 2. grep -E '^[a-z_-]+ = \[': Filter to lines that define groups
63-
# - ^[a-z_-]+: Group name at start of line (lowercase letters, hyphens, underscores)
62+
# 2. grep -E '^[a-z0-9_-]+ = \[': Filter to lines that define groups
63+
# - ^[a-z0-9_-]+: Group name at start of line (lowercase letters, digits, hyphens, underscores)
6464
# - = \[: Followed by space, equals sign, space, opening bracket
6565
# 3. cut -d' ' -f1: Extract just the group name
6666
# - -d' ': Use space as delimiter
@@ -75,7 +75,7 @@ AVAILABLE_GROUPS=$(
7575
in_section && /^\[/ { exit }
7676
in_section { print }
7777
' "$PYPROJECT_TOML" |
78-
grep -E '^[a-z_-]+ = \[' |
78+
grep -E '^[a-z0-9_-]+ = \[' |
7979
cut -d' ' -f1 |
8080
tr '\n' ' '
8181
)
@@ -109,7 +109,7 @@ ENSURE_MODE=false
109109

110110
# Groups excluded from --all-groups due to mutual conflicts in pyproject.toml.
111111
# tamm-export is omitted because it's opt-in only (never in default-groups or --all-groups).
112-
CONFLICTING_GROUPS=("highest_tested_torch" "lowest_tested_torch")
112+
CONFLICTING_GROUPS=("torch_2_8" "torch_2_9" "torch_2_10" "torch_2_11")
113113

114114
show_help() {
115115
echo "Usage: $0 [OPTIONS]"
@@ -127,6 +127,7 @@ show_help() {
127127
echo ""
128128
echo "Environment variables:"
129129
echo " VENV Virtual environment name, overrides --venv (default: .venv)"
130+
echo " TORCH_GROUP Torch dependency group to pin; source of truth for torch pinning"
130131
echo ""
131132
echo "Available dependency groups: $AVAILABLE_GROUPS"
132133
echo "Conflicting groups (excluded from --all-groups): ${CONFLICTING_GROUPS[*]}"
@@ -135,8 +136,8 @@ show_help() {
135136
echo " $0 --python-version 3.11 # Setup with dev group only"
136137
echo " $0 --python-version 3.11 --with-docs # Setup with dev and docs groups"
137138
echo " $0 --python-version 3.11 --all-groups # Setup with all non-conflicting groups"
138-
echo " $0 --python-version 3.11 --all-groups --with-highest_tested_torch # Setup with all groups and highest torch"
139-
echo " $0 --python-version 3.11 --all-groups --with-lowest_tested_torch # Setup with all groups and lowest torch"
139+
echo " TORCH_GROUP=torch_2_11 $0 --python-version 3.11 --all-groups # Setup with all groups and torch 2.11"
140+
echo " TORCH_GROUP=torch_2_8 $0 --python-version 3.11 --all-groups # Setup with all groups and torch 2.8"
140141
echo " $0 --python-version 3.11 --venv .venv-exp # Setup with custom venv name"
141142
echo " $0 --python-version 3.11 --with-docs --venv .venv-exp # Setup with docs group and custom venv name"
142143
echo " $0 --python-version 3.12 # Setup with Python 3.12"
@@ -222,6 +223,7 @@ validate_groups() {
222223
# Validate dependency group names early
223224
[[ ${#EXTRA_GROUPS[@]} -gt 0 ]] && validate_groups "${EXTRA_GROUPS[@]}"
224225
[[ ${#EXCLUDE_GROUPS[@]} -gt 0 ]] && validate_groups "${EXCLUDE_GROUPS[@]}"
226+
[[ -n "${TORCH_GROUP:-}" ]] && validate_groups "$TORCH_GROUP"
225227

226228
# Check for conflicts between --with-<group> and --without-<group>
227229
if [[ ${#EXTRA_GROUPS[@]} -gt 0 && ${#EXCLUDE_GROUPS[@]} -gt 0 ]]; then
@@ -267,24 +269,35 @@ if [[ "$ENSURE_MODE" == "true" ]] && [ -f "$VENV/bin/python" ]; then
267269
for GROUP in "${EXTRA_GROUPS[@]}"; do
268270
case "$GROUP" in
269271
docs) IMPORT_STMTS+="; import sphinx" ;;
270-
highest_tested_torch | lowest_tested_torch)
271-
IMPORT_STMTS+="; import torchao"
272-
EXPECTED_TORCH="$(group_torch_pin "$GROUP")"
273-
# These groups always pin torch, so an empty result means the
274-
# pyproject parse regressed — fail loudly instead of silently
275-
# skipping the version check (which would reintroduce the bug).
276-
if [[ -z "$EXPECTED_TORCH" ]]; then
277-
echo "Error: could not parse a torch pin for group '$GROUP' in $PYPROJECT_TOML" >&2
278-
exit 1
279-
fi
280-
IMPORT_STMTS+="; import torch; assert torch.__version__.split('+')[0] == '$EXPECTED_TORCH'"
281-
;;
282272
rio) IMPORT_STMTS+="; import turi_lightning" ;;
283273
tamm-export) IMPORT_STMTS+="; import tamm_export" ;;
284274
esac
285275
done
286276
fi
287277

278+
# TORCH_GROUP is the single source of truth for torch pinning; fall back
279+
# to a --with-torch_2_* flag for direct, non-Make invocations. Checked
280+
# unconditionally rather than only when present in EXTRA_GROUPS, since
281+
# TORCH_GROUP drives the sync regardless of what's in EXTRA_GROUPS.
282+
EXPECTED_GROUP="${TORCH_GROUP:-}"
283+
if [[ -z "$EXPECTED_GROUP" ]]; then
284+
for GROUP in "${EXTRA_GROUPS[@]:-}"; do
285+
[[ " ${CONFLICTING_GROUPS[*]} " == *" ${GROUP} "* ]] && EXPECTED_GROUP="$GROUP"
286+
done
287+
fi
288+
if [[ -n "$EXPECTED_GROUP" ]]; then
289+
IMPORT_STMTS+="; import torchao"
290+
EXPECTED_TORCH="$(group_torch_pin "$EXPECTED_GROUP")"
291+
# These groups always pin torch, so an empty result means the
292+
# pyproject parse regressed — fail loudly instead of silently
293+
# skipping the version check (which would reintroduce the bug).
294+
if [[ -z "$EXPECTED_TORCH" ]]; then
295+
echo "Error: could not parse a torch pin for '$EXPECTED_GROUP' in $PYPROJECT_TOML" >&2
296+
exit 1
297+
fi
298+
IMPORT_STMTS+="; import torch; assert torch.__version__.split('+')[0] == '$EXPECTED_TORCH'"
299+
fi
300+
288301
if "$VENV/bin/python" -c "$IMPORT_STMTS" 2>/dev/null; then
289302
exit 0
290303
fi
@@ -324,9 +337,13 @@ echo "[2/3] Installing dependencies..."
324337
SYNC_CMD=(uv sync --active)
325338
if [[ "$ALL_GROUPS" == "true" ]]; then
326339
SYNC_CMD+=(--all-groups)
327-
# Exclude conflicting groups unless explicitly requested via --with-*
340+
# Exclude conflicting torch groups other than the one TORCH_GROUP or
341+
# --with-<group> selects, so --all-groups doesn't try to sync every
342+
# torch_2_* group at once. If both TORCH_GROUP and --with-<other-group>
343+
# name different groups, neither gets excluded here and `uv sync` itself
344+
# rejects the combination via its own conflicting-groups resolution.
328345
for GROUP in "${CONFLICTING_GROUPS[@]}"; do
329-
if [[ ! " ${EXTRA_GROUPS[*]:-} " == *" ${GROUP} "* ]]; then
346+
if [[ "$GROUP" != "${TORCH_GROUP:-}" ]] && [[ ! " ${EXTRA_GROUPS[*]:-} " == *" ${GROUP} "* ]]; then
330347
SYNC_CMD+=(--no-group "$GROUP")
331348
fi
332349
done
@@ -335,6 +352,14 @@ elif [[ ${#EXTRA_GROUPS[@]} -gt 0 ]]; then
335352
SYNC_CMD+=(--group "$GROUP")
336353
done
337354
fi
355+
# TORCH_GROUP is the single source of truth for torch pinning: append it
356+
# unconditionally (already covered under --all-groups by not being
357+
# excluded above). A disagreeing --with-<other-torch-group> ends up as a
358+
# second, different --group flag here, which `uv sync` itself rejects via
359+
# its conflicting-groups resolution rather than a bespoke check.
360+
if [[ -n "${TORCH_GROUP:-}" && "$ALL_GROUPS" != "true" ]]; then
361+
SYNC_CMD+=(--group "$TORCH_GROUP")
362+
fi
338363
# Apply explicit group exclusions (e.g., --without-coreai)
339364
if [[ ${#EXCLUDE_GROUPS[@]} -gt 0 ]]; then
340365
for GROUP in "${EXCLUDE_GROUPS[@]}"; do

0 commit comments

Comments
 (0)