Skip to content

Commit 7f2a662

Browse files
Merge branch 'main' into vela-6d-io
2 parents df556e6 + def4c64 commit 7f2a662

File tree

475 files changed

+22417
-8716
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

475 files changed

+22417
-8716
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6fc0ad22f0a07b6f38d138861c56a765d5a9bb02
1+
e7152ff8a6a929a0db7f3f4a72a5b6d471769cd3

.ci/scripts/setup-linux.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ set -exu
1111
source "$(dirname "${BASH_SOURCE[0]}")/utils.sh"
1212

1313
read -r BUILD_TOOL BUILD_MODE EDITABLE < <(parse_args "$@")
14+
echo "Build tool: $BUILD_TOOL, Mode: $BUILD_MODE"
1415

1516
# As Linux job is running inside a Docker container, all of its dependencies
1617
# have already been installed, so we use PyTorch build from source here instead

.ci/scripts/test_backend_linux.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
set -eux
8+
9+
SUITE=$1
10+
FLOW=$2
11+
ARTIFACT_DIR=$3
12+
13+
REPORT_FILE="$ARTIFACT_DIR/test-report-$FLOW-$SUITE.csv"
14+
15+
echo "Running backend test job for suite $SUITE, flow $FLOW."
16+
echo "Saving job artifacts to $ARTIFACT_DIR."
17+
18+
# The generic Linux job chooses to use base env, not the one setup by the image
19+
eval "$(conda shell.bash hook)"
20+
CONDA_ENV=$(conda env list --json | jq -r ".envs | .[-1]")
21+
conda activate "${CONDA_ENV}"
22+
23+
export PYTHON_EXECUTABLE=python
24+
25+
# CMake options to use, in addition to the defaults.
26+
EXTRA_BUILD_ARGS=""
27+
28+
if [[ "$FLOW" == *qnn* ]]; then
29+
# Setup QNN sdk and deps - note that this is a bit hacky due to the nature of the
30+
# Qualcomm build. TODO (gjcomer) Clean this up once the QNN pybinding integration is
31+
# cleaned up.
32+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-linux.sh --build-tool cmake
33+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-qnn-deps.sh
34+
PYTHON_EXECUTABLE=python bash .ci/scripts/build-qnn-sdk.sh
35+
QNN_X86_LIB_DIR=`realpath build-x86/lib/`
36+
QNN_SDK_ROOT="/tmp/qnn/2.28.0.241029"
37+
export LD_LIBRARY_PATH"=$QNN_X86_LIB_DIR:$QNN_SDK_ROOT/lib/x86_64-linux-clang/:${LD_LIBRARY_PATH:-}"
38+
39+
# TODO Get SDK root from install scripts
40+
EXTRA_BUILD_ARGS+=" -DEXECUTORCH_BUILD_QNN=ON -DQNN_SDK_ROOT=$QNN_SDK_ROOT"
41+
fi
42+
43+
if [[ "$FLOW" == *vulkan* ]]; then
44+
# Setup swiftshader and Vulkan SDK which are required to build the Vulkan delegate
45+
source .ci/scripts/setup-vulkan-linux-deps.sh
46+
47+
EXTRA_BUILD_ARGS+=" -DEXECUTORCH_BUILD_VULKAN=ON"
48+
fi
49+
50+
# We need the runner to test the built library.
51+
PYTHON_EXECUTABLE=python CMAKE_ARGS="$EXTRA_BUILD_ARGS" .ci/scripts/setup-linux.sh --build-tool cmake --build-mode Release --editable true
52+
53+
EXIT_CODE=0
54+
python -m executorch.backends.test.suite.runner $SUITE --flow $FLOW --report "$REPORT_FILE" || EXIT_CODE=$?
55+
56+
# Generate markdown summary.
57+
python -m executorch.backends.test.suite.generate_markdown_summary "$REPORT_FILE" > ${GITHUB_STEP_SUMMARY:-"step_summary.md"} --exit-code $EXIT_CODE

.ci/scripts/test_backend_macos.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
set -eux
8+
9+
SUITE=$1
10+
FLOW=$2
11+
ARTIFACT_DIR=$3
12+
13+
REPORT_FILE="$ARTIFACT_DIR/test-report-$FLOW-$SUITE.csv"
14+
15+
echo "Running backend test job for suite $SUITE, flow $FLOW."
16+
echo "Saving job artifacts to $ARTIFACT_DIR."
17+
18+
${CONDA_RUN} --no-capture-output pip install awscli==1.37.21
19+
20+
bash .ci/scripts/setup-conda.sh
21+
eval "$(conda shell.bash hook)"
22+
23+
PYTHON_EXECUTABLE=python
24+
${CONDA_RUN} --no-capture-output .ci/scripts/setup-macos.sh --build-tool cmake --build-mode Release
25+
26+
EXIT_CODE=0
27+
${CONDA_RUN} --no-capture-output python -m executorch.backends.test.suite.runner $SUITE --flow $FLOW --report "$REPORT_FILE" || EXIT_CODE=$?
28+
29+
# Generate markdown summary.
30+
${CONDA_RUN} --no-capture-output python -m executorch.backends.test.suite.generate_markdown_summary "$REPORT_FILE" > ${GITHUB_STEP_SUMMARY:-"step_summary.md"} --exit-code $EXIT_CODE

.ci/scripts/test_huggingface_optimum_model.py

Lines changed: 108 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import argparse
2+
import gc
3+
import logging
4+
import math
25
import subprocess
36
import tempfile
47
from pathlib import Path
8+
from typing import List
59

610
import torch
711
from datasets import load_dataset
@@ -15,6 +19,7 @@
1519
)
1620
from transformers import (
1721
AutoConfig,
22+
AutoModelForCausalLM,
1823
AutoModelForImageClassification,
1924
AutoProcessor,
2025
AutoTokenizer,
@@ -37,6 +42,56 @@ def cli_export(command, model_dir):
3742
print(f"Export failed with error: {e}")
3843

3944

45+
def check_causal_lm_output_quality(
46+
model_id: str, generated_tokens: List[int], max_perplexity_threshold: float = 100.0
47+
):
48+
"""
49+
Evaluates the quality of text generated by a causal language model by calculating its perplexity.
50+
51+
Args:
52+
model_id: HuggingFace model identifier (e.g., "google/gemma2-2b")
53+
generated_tokens: The tokens generated by the exported model to evaluate
54+
max_perplexity_threshold: Maximum acceptable perplexity (lower is better)
55+
56+
Returns:
57+
tuple: (is_quality_ok, reason) with boolean result and explanation
58+
"""
59+
logging.info(f"Starting perplexity check with model '{model_id}' ...")
60+
# Load model
61+
model = AutoModelForCausalLM.from_pretrained(
62+
model_id,
63+
low_cpu_mem_usage=True,
64+
use_cache=False,
65+
torch_dtype=torch.bfloat16,
66+
)
67+
68+
with torch.no_grad():
69+
outputs = model(input_ids=generated_tokens, labels=generated_tokens)
70+
71+
# Get the loss (negative log-likelihood)
72+
loss = outputs.loss.item()
73+
74+
# Calculate perplexity (exp of the average negative log-likelihood)
75+
perplexity = math.exp(loss)
76+
77+
is_quality_ok = perplexity <= max_perplexity_threshold
78+
if is_quality_ok:
79+
logging.info(
80+
f"✓ Perplexity check passed: {perplexity:.2f} <= {max_perplexity_threshold}"
81+
)
82+
else:
83+
logging.warning(
84+
f"✗ Perplexity check failed: {perplexity:.2f} > {max_perplexity_threshold}"
85+
)
86+
87+
# Clean up immediately
88+
del model
89+
del outputs
90+
gc.collect()
91+
92+
return is_quality_ok
93+
94+
4095
def test_text_generation(model_id, model_dir, recipe, *, quantize=True, run_only=False):
4196
command = [
4297
"optimum-cli",
@@ -51,7 +106,19 @@ def test_text_generation(model_id, model_dir, recipe, *, quantize=True, run_only
51106
"--output_dir",
52107
model_dir,
53108
]
54-
if "coreml" in recipe:
109+
if "xnnpack" in recipe:
110+
command += [
111+
"--use_custom_sdpa",
112+
"--use_custom_kv_cache",
113+
]
114+
if quantize:
115+
command += [
116+
"--qlinear",
117+
"8da4w",
118+
"--qembedding",
119+
"8w",
120+
]
121+
elif "coreml" in recipe:
55122
command += [
56123
"--disable_dynamic_shapes",
57124
]
@@ -63,7 +130,9 @@ def test_text_generation(model_id, model_dir, recipe, *, quantize=True, run_only
63130
"8w",
64131
]
65132
else:
66-
assert not quantize, "Quantization is not supported for non-CoreML recipes yet"
133+
assert (
134+
not quantize
135+
), "Quantization is only supported for XnnPack and CoreML recipes at the moment."
67136

68137
if not run_only:
69138
cli_export(command, model_dir)
@@ -77,6 +146,14 @@ def test_text_generation(model_id, model_dir, recipe, *, quantize=True, run_only
77146
max_seq_len=64,
78147
)
79148
print(f"\nGenerated text:\n\t{generated_text}")
149+
generated_tokens = tokenizer(generated_text, return_tensors="pt").input_ids
150+
151+
# Free memory before loading eager for quality check
152+
del model
153+
del tokenizer
154+
gc.collect()
155+
156+
assert check_causal_lm_output_quality(model_id, generated_tokens) is True
80157

81158

82159
def test_fill_mask(model_id, model_dir, recipe, *, quantize=True, run_only=False):
@@ -278,23 +355,39 @@ def test_vit(model_id, model_dir, recipe, *, quantize=False, run_only=False):
278355
)
279356
args = parser.parse_args()
280357

281-
model_to_model_id_and_test_function = {
282-
"smollm": ("HuggingFaceTB/SmolLM2-135M", test_text_generation), # works
283-
"qwen3": ("Qwen/Qwen3-0.6B", test_text_generation), # works
284-
"olmo": ("allenai/OLMo-1B-hf", test_text_generation), # works
285-
"gemma3": ("unsloth/gemma-3-1b-it", test_text_generation), # does not export
286-
"phi4": (
358+
_text_generation_mapping = {
359+
"llama3.2-1b": ("NousResearch/Llama-3.2-1B", test_text_generation),
360+
"qwen3-0.6b": ("Qwen/Qwen3-0.6B", test_text_generation),
361+
"qwen3-1.7b": ("Qwen/Qwen3-1.7B", test_text_generation),
362+
"gemma3-1b": (
363+
"unsloth/gemma-3-1b-it",
364+
test_text_generation,
365+
), # does not export for CoreML
366+
"phi4-mini": (
287367
"microsoft/Phi-4-mini-instruct",
288368
test_text_generation,
289-
), # fails to lower
290-
"llama3": ("NousResearch/Llama-3.2-1B", test_text_generation), # works
291-
"bert": ("google-bert/bert-base-uncased", test_fill_mask), # works
292-
"roberta": ("FacebookAI/xlmcl-roberta-base", test_fill_mask), # works
293-
"distilbert": ("distilbert/distilbert-base-uncased", test_fill_mask), # works
294-
"whisper": ("openai/whisper-tiny", test_whisper), # works
369+
), # fails to lower for CoreML
370+
"smollm2-135m": ("HuggingFaceTB/SmolLM2-135M", test_text_generation),
371+
"smollm3-3b": ("HuggingFaceTB/SmolLM3-3B", test_text_generation),
372+
"olmo-1b": ("allenai/OLMo-1B-hf", test_text_generation),
373+
}
374+
375+
_mask_fill_mapping = {
376+
"bert": ("google-bert/bert-base-uncased", test_fill_mask),
377+
"roberta": ("FacebookAI/xlmcl-roberta-base", test_fill_mask),
378+
"distilbert": ("distilbert/distilbert-base-uncased", test_fill_mask),
379+
}
380+
381+
_misc_model_mapping = {
382+
"whisper": ("openai/whisper-tiny", test_whisper),
295383
"t5": ("google-t5/t5-small", test_t5), # CoreML runime failure
296-
"vit": ("google/vit-base-patch16-224", test_vit), # works
384+
"vit": ("google/vit-base-patch16-224", test_vit),
297385
}
386+
387+
model_to_model_id_and_test_function = (
388+
_text_generation_mapping | _mask_fill_mapping | _misc_model_mapping
389+
)
390+
298391
if args.model not in model_to_model_id_and_test_function:
299392
raise ValueError(
300393
f"Unknown model name: {args.model}. Available models: {model_to_model_id_and_test_function.keys()}"

.ci/scripts/test_ios_ci.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ say() {
3636

3737
say "Cloning the Demo App"
3838

39-
git clone --depth 1 https://github.com/pytorch-labs/executorch-examples.git
39+
git clone --depth 1 https://github.com/meta-pytorch/executorch-examples.git
4040

4141
say "Installing CoreML Backend Requirements"
4242

.ci/scripts/unittest-buck2.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ set -eux
1111
# TODO: can't query //kernels/prim_ops because of non-buckified stuff in OSS.
1212
buck2 query "//backends/apple/... + //backends/example/... + \
1313
//backends/mediatek/... + //backends/transforms/... + \
14-
//backends/xnnpack/... + //configurations/... + //kernels/aten/... + \
15-
//kernels/optimized/... + //kernels/portable/... + //kernels/quantized/... + \
16-
//kernels/test/... + //runtime/... + //schema/... + //test/... + //util/..."
14+
//backends/xnnpack/... + //configurations/... + //extension/flat_tensor: + \
15+
//extension/llm/runner: + //kernels/aten/... + //kernels/optimized/... + \
16+
//kernels/portable/... + //kernels/quantized/... + //kernels/test/... + \
17+
//runtime/... + //schema/... + //test/... + //util/..."
1718

1819
# TODO: optimized ops are unbuildable because they now use ATen; put
1920
# them back after we can use PyTorch in OSS buck.

.ci/scripts/utils.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ build_executorch_runner_cmake() {
131131
else
132132
CXXFLAGS=""
133133
fi
134-
# This command uses buck2 to gather source files and buck2 could crash flakily
135-
# on MacOS
136134
CXXFLAGS="$CXXFLAGS" retry cmake -DPYTHON_EXECUTABLE="${PYTHON_EXECUTABLE}" -DCMAKE_BUILD_TYPE="${1:-Release}" ..
137135
popd || return
138136

.github/workflows/add-unanswered-to-project.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
name: Add Open External Contributor PRs and Issues to PyTorch Org Project 136
22

33
on:
4-
# schedule:
5-
# - cron: '0 * * * *'
64
workflow_dispatch:
7-
5+
pull_request:
6+
paths:
7+
.github/workflows/add-unanswered-to-project.yml
88
jobs:
99
add_to_project:
1010
runs-on: ubuntu-latest

.github/workflows/nightly.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,51 @@ jobs:
3636
uses: ./.github/workflows/_link_check.yml
3737
with:
3838
ref: ${{ github.sha }}
39+
40+
backend-test-linux:
41+
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
42+
strategy:
43+
fail-fast: false
44+
matrix:
45+
flow: [
46+
qnn, qnn_16a16w, qnn_16a8w, qnn_16a4w, qnn_16a4w_block, qnn_8a8w,
47+
vulkan, vulkan_static_int8_per_channel,
48+
xnnpack, xnnpack_dynamic_int8_per_channel, xnnpack_static_int8_per_channel, xnnpack_static_int8_per_tensor
49+
]
50+
suite: [models, operators]
51+
with:
52+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
53+
runner: linux.4xlarge.memory
54+
docker-image: ci-image:executorch-ubuntu-22.04-clang12
55+
submodules: recursive
56+
timeout: 120
57+
upload-artifact: test-report-${{ matrix.flow }}-${{ matrix.suite }}
58+
script: |
59+
set -eux
60+
61+
source .ci/scripts/test_backend_linux.sh "${{ matrix.suite }}" "${{ matrix.flow }}" "${RUNNER_ARTIFACT_DIR}"
62+
63+
backend-test-macos:
64+
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main
65+
permissions:
66+
id-token: write
67+
contents: read
68+
strategy:
69+
fail-fast: false
70+
matrix:
71+
flow: [coreml, coreml_static_int8]
72+
suite: [models, operators]
73+
with:
74+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
75+
runner: macos-m1-stable
76+
python-version: 3.12
77+
submodules: recursive
78+
timeout: 120
79+
upload-artifact: test-report-${{ matrix.flow }}-${{ matrix.suite }}
80+
script: |
81+
set -eux
82+
83+
# This is needed to get the prebuilt PyTorch wheel from S3
84+
${CONDA_RUN} --no-capture-output pip install awscli==1.37.21
85+
86+
source .ci/scripts/test_backend_macos.sh "${{ matrix.suite }}" "${{ matrix.flow }}" "${RUNNER_ARTIFACT_DIR}"

0 commit comments

Comments
 (0)