Skip to content

Commit 3285bb2

Browse files
Update
[ghstack-poisoned]
2 parents d761fdb + ba0e56e commit 3285bb2

35 files changed

Lines changed: 845 additions & 381 deletions

File tree

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# LICENSE file in the root directory of this source tree.
77

88
set -ex
9+
910
# shellcheck source=/dev/null
1011
source "$(dirname "${BASH_SOURCE[0]}")/utils.sh"
1112

@@ -50,21 +51,21 @@ PT2E_QUANTIZE="${PT2E_QUANTIZE:-}"
5051
# Default CMake Build Type to release mode
5152
CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release}
5253

53-
if [[ $# -lt 5 ]]; then # Assuming 4 mandatory args
54-
echo "Expecting atleast 5 positional arguments"
55-
echo "Usage: [...]"
56-
fi
5754
if [[ -z "${MODEL_NAME:-}" ]]; then
5855
echo "Missing model name, exiting..."
5956
exit 1
6057
fi
6158

62-
6359
if [[ -z "${MODE:-}" ]]; then
6460
echo "Missing mode, choose openvino or xnnpack, exiting..."
6561
exit 1
6662
fi
6763

64+
if [[ -z "${VIDEO_PATH:-}" ]]; then
65+
echo "Missing video path, exiting..."
66+
exit 1
67+
fi
68+
6869
if [[ -z "${PYTHON_EXECUTABLE:-}" ]]; then
6970
PYTHON_EXECUTABLE=python3
7071
fi
@@ -75,21 +76,13 @@ if [[ "${MODE}" =~ .*openvino.* ]]; then
7576
OPENVINO=ON
7677
TARGET_LIBS="$TARGET_LIBS openvino_backend "
7778

78-
git clone https://github.com/openvinotoolkit/openvino.git
79-
cd openvino && git b16b776ac119dafda51f69a80f1e6b7376d02c3b
80-
git submodule update --init --recursive
81-
sudo ./install_build_dependencies.sh
82-
mkdir build && cd build
83-
cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_PYTHON=ON
84-
make -j$(nproc)
85-
86-
cd ..
87-
cmake --install build --prefix dist
88-
89-
source dist/setupvars.sh
90-
cd ../backends/openvino
91-
pip install -r requirements.txt
92-
cd ../../
79+
# Install specific OpenVINO runtime from pip.
80+
$PYTHON_EXECUTABLE -m pip install --pre openvino==2026.1.0.dev20260131 --extra-index-url https://storage.openvinotoolkit.org/simple/wheels/nightly
81+
$PYTHON_EXECUTABLE -m pip install -r backends/openvino/requirements.txt
82+
83+
# Set OPENVINO_LIB_PATH so the C++ demo runner can also find libopenvino_c.so.
84+
OPENVINO_LIB_PATH=$($PYTHON_EXECUTABLE -c "import openvino, os, glob; print(sorted(glob.glob(os.path.join(os.path.dirname(openvino.__file__), 'libs', 'libopenvino_c.so*')))[-1])")
85+
export OPENVINO_LIB_PATH
9386
else
9487
OPENVINO=OFF
9588
fi
@@ -103,9 +96,10 @@ fi
10396

10497
which "${PYTHON_EXECUTABLE}"
10598

99+
TORCH_URL=https://download.pytorch.org/whl/cpu
106100

107-
DIR="examples/models/yolo12"
108-
$PYTHON_EXECUTABLE -m pip install -r ${DIR}/requirements.txt
101+
DIR="examples/models/yolo26"
102+
$PYTHON_EXECUTABLE -m pip install --upgrade-strategy only-if-needed --extra-index-url "$TORCH_URL" -r ${DIR}/requirements.txt
109103

110104
cmake_install_executorch_libraries() {
111105
rm -rf cmake-out
@@ -142,11 +136,11 @@ cmake_install_executorch_libraries() {
142136

143137
echo $TARGET_LIBS
144138
export CMAKE_BUILD_ARGS="--target $TARGET_LIBS"
145-
pip install . --no-build-isolation
139+
$PYTHON_EXECUTABLE -m pip install . --no-build-isolation
146140
}
147141

148142
cmake_build_demo() {
149-
echo "Building yolo12 runner"
143+
echo "Building yolo26 runner"
150144
retry cmake \
151145
-DCMAKE_BUILD_TYPE="$CMAKE_BUILD_TYPE" \
152146
-DUSE_OPENVINO_BACKEND="$OPENVINO" \
@@ -174,24 +168,29 @@ prepare_artifacts_upload() {
174168

175169

176170
# Export model.
177-
EXPORTED_MODEL_NAME="${MODEL_NAME}_fp32_${MODE}.pte"
178-
echo "Exporting ${EXPORTED_MODEL_NAME}"
179171
EXPORT_ARGS="--model_name=${MODEL_NAME} --backend=${MODE}"
172+
if [[ -n "${PT2E_QUANTIZE}" ]]; then
173+
EXPORTED_MODEL_NAME="${MODEL_NAME}_int8_${MODE}.pte"
174+
EXPORT_ARGS="${EXPORT_ARGS} --quantize --video_path=${VIDEO_PATH}"
175+
else
176+
EXPORTED_MODEL_NAME="${MODEL_NAME}_fp32_${MODE}.pte"
177+
fi
178+
echo "Exporting ${EXPORTED_MODEL_NAME}"
180179

181180
# Add dynamically linked library location
182181
cmake_install_executorch_libraries
183182

184-
$PYTHON_EXECUTABLE -m examples.models.yolo12.export_and_validate ${EXPORT_ARGS}
183+
$PYTHON_EXECUTABLE -m examples.models.yolo26.export_and_validate ${EXPORT_ARGS}
185184

186185

187186
RUNTIME_ARGS="--model_path=${EXPORTED_MODEL_NAME} --input_path=${VIDEO_PATH}"
188187
# Check build tool.
189188
cmake_build_demo
190-
# Run yolo12 runner
189+
# Run yolo26 runner
191190
NOW=$(date +"%H:%M:%S")
192-
echo "Starting to run yolo12 runner at ${NOW}"
191+
echo "Starting to run yolo26 runner at ${NOW}"
193192
# shellcheck source=/dev/null
194-
cmake-out/examples/models/yolo12/Yolo12DetectionDemo ${RUNTIME_ARGS} > result.txt
193+
cmake-out/examples/models/yolo26/Yolo26DetectionDemo ${RUNTIME_ARGS} > result.txt
195194
NOW=$(date +"%H:%M:%S")
196195
echo "Finished at ${NOW}"
197196

.github/labeler.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"module: arm":
2+
- changed-files:
3+
- any-glob-to-any-file:
4+
- 'backends/arm/**'
5+
- 'examples/arm/**'
6+
- 'docs/source/backends/arm-*/**'
7+
- 'docs/source/embedded-arm-ethos-u.md'
8+
- 'docs/source/android-arm-vgf.md'
9+
- 'docs/source/arm-delegate-runtime-build.svg'
10+
11+
ciflow/trunk:
12+
- changed-files:
13+
- any-glob-to-any-file:
14+
- 'backends/arm/**'
15+
- 'examples/arm/**'

.github/workflows/labeler.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: Labeler
2+
on:
3+
pull_request_target:
4+
types: [opened, synchronize, reopened, ready_for_review]
5+
6+
permissions:
7+
contents: read
8+
pull-requests: write
9+
10+
jobs:
11+
label:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/labeler@v5

.github/workflows/pull.yml

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,8 @@ jobs:
857857
id-token: write
858858
contents: read
859859
strategy:
860+
matrix:
861+
model: [mv2, mv3, dl3]
860862
fail-fast: false
861863
with:
862864
runner: linux.2xlarge
@@ -868,9 +870,58 @@ jobs:
868870
# The generic Linux job chooses to use base env, not the one setup by the image
869871
CONDA_ENV=$(conda env list --json | jq -r ".envs | .[-1]")
870872
conda activate "${CONDA_ENV}"
873+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-linux.sh --build-tool cmake
874+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-qnn-deps.sh
875+
PYTHON_EXECUTABLE=python bash .ci/scripts/build-qnn-sdk.sh
876+
PYTHON_EXECUTABLE=python bash .ci/scripts/test_model.sh ${{ matrix.model }} "cmake" "qnn"
877+
878+
test-qnn-testsuite-linux:
879+
name: test-qnn-testsuite-linux
880+
permissions:
881+
id-token: write
882+
contents: read
883+
uses: ./.github/workflows/_test_backend.yml
884+
with:
885+
backend: qnn
886+
flows: '["qnn"]'
887+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
888+
timeout: 120
889+
run-linux: true
890+
runner-linux: linux.2xlarge
891+
892+
test-qnn-passes-linux:
893+
name: test-qnn-passes-linux
894+
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
895+
permissions:
896+
id-token: write
897+
contents: read
898+
strategy:
899+
fail-fast: false
900+
with:
901+
runner: linux.2xlarge
902+
docker-image: ci-image:executorch-ubuntu-22.04-qnn-sdk
903+
submodules: 'recursive'
904+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
905+
timeout: 30
906+
script: |
907+
# The generic Linux job chooses to use base env, not the one setup by the image
908+
CONDA_ENV=$(conda env list --json | jq -r ".envs | .[-1]")
909+
conda activate "${CONDA_ENV}"
910+
911+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-qnn-deps.sh
912+
# Source (not bash) so QNN_SDK_ROOT stays in the environment
913+
PYTHON_EXECUTABLE=python source .ci/scripts/build-qnn-sdk.sh
914+
915+
# Editable install so the PyQnnManagerAdaptor .so built by build-qnn-sdk.sh
916+
# is visible in the source tree (the _passes import chain pulls it in transitively)
917+
CMAKE_ARGS="-DEXECUTORCH_BUILD_QNN=ON -DQNN_SDK_ROOT=$QNN_SDK_ROOT -DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON" \
918+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-linux.sh --build-tool cmake --editable true
919+
920+
# test_mha_to_sha imports oss_scripts/llama which transitively needs torchtune
921+
pip install -r requirements-examples.txt
871922
872-
# placeholder for running test_qnn_delegate.py, can use matrix such that we can trigger different jobs, refers to test-llama-runner-qnn-linux
873-
# reminder: make sure each job runs fast
923+
# Run QNN pass unit tests
924+
pytest -xvs backends/qualcomm/tests/test_passes.py
874925
875926
test-phi-3-mini-runner-linux:
876927
name: test-phi-3-mini-runner-linux

.lintrunner.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ exclude_patterns = [
225225
'extension/llm/tokenizers/**',
226226
'backends/cadence/utils/FACTO',
227227
'examples/cuda',
228+
'examples/qualcomm',
228229
'kernels/portable',
229230
# File contains @generated
230231
'extension/llm/custom_ops/spinquant/fast_hadamard_transform_special.h',

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ ExecuTorch powers on-device AI at scale across Meta's family of apps, VR/AR devi
204204

205205
**Multimodal:** [Llava](examples/models/llava/README.md) (vision-language), [Voxtral](examples/models/voxtral/README.md) (audio-language), [Gemma](examples/models/gemma3) (vision-language)
206206

207-
**Vision/Speech:** [MobileNetV2](https://github.com/meta-pytorch/executorch-examples/tree/main/mv2), [DeepLabV3](https://github.com/meta-pytorch/executorch-examples/tree/main/dl3), [Whisper](examples/models/whisper/README.md) <!-- @lint-ignore -->
207+
**Vision/Speech:** [MobileNetV2](https://github.com/meta-pytorch/executorch-examples/tree/main/mv2), [DeepLabV3](https://github.com/meta-pytorch/executorch-examples/tree/main/dl3), [YOLO26](examples/models/yolo26/README.md), [Whisper](examples/models/whisper/README.md) <!-- @lint-ignore -->
208208

209209
**Resources:** [`examples/`](examples/) directory • [executorch-examples](https://github.com/meta-pytorch/executorch-examples) out-of-tree demos • [Optimum-ExecuTorch](https://github.com/huggingface/optimum-executorch) for HuggingFace models • [Unsloth](https://docs.unsloth.ai/new/deploy-llms-phone) for fine-tuned LLM deployment <!-- @lint-ignore -->
210210

backends/cadence/aot/compiler_funcs.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
import logging
1010
import operator
11-
from typing import Any, Optional, Union
11+
from collections.abc import Mapping, Sequence
12+
from typing import Any, cast, Optional, Union
1213

1314
import torch
1415
from torch._inductor.decomposition import remove_decompositions
@@ -301,23 +302,27 @@ def __init__(
301302
"Warning: Using pre-quantized inputs. This should only be done when calibration has been confirmed."
302303
"Incorrect quantization parameters can lead to significant accuracy degradation."
303304
)
304-
if isinstance(input_args, list):
305-
self.quant_args = extract_input_quant_params_from_graph(module, input_args)
306-
elif isinstance(input_args, dict):
305+
if isinstance(input_args, Sequence) and not isinstance(
306+
input_args, (str, bytes)
307+
):
308+
self.quant_args = extract_input_quant_params_from_graph(
309+
module, list(input_args)
310+
)
311+
elif isinstance(input_args, Mapping):
307312
# dict[int, QuantArgs] — use directly
308313
# dict[int, list[str]] — extract quant params from graph, keyed by input index
309314
first_value = next(iter(input_args.values()), None)
310315
if (
311-
isinstance(first_value, (list, tuple))
316+
isinstance(first_value, (list, tuple, Sequence))
317+
and not isinstance(first_value, (str, bytes))
312318
and first_value
313319
and isinstance(first_value[0], str)
314320
):
315321
# Values are lists of node names: extract quant params and map
316322
# to the caller-specified input indices.
317323
for input_idx, node_names in input_args.items():
318-
assert isinstance(node_names, list)
319324
extracted = extract_input_quant_params_from_graph(
320-
module, node_names
325+
module, list(cast(Sequence[str], node_names))
321326
)
322327
# Use the first extracted quant params for this input index.
323328
if extracted:
@@ -430,6 +435,7 @@ def _get_transparent_ops() -> set[Any]:
430435
torch.ops.aten.view.default,
431436
torch.ops.aten.reshape.default,
432437
torch.ops.aten.split.Tensor,
438+
torch.ops.aten.chunk.default,
433439
torch.ops.aten.slice_copy.Tensor,
434440
torch.ops.aten.permute_copy.default,
435441
torch.ops.aten.permute.default,

0 commit comments

Comments
 (0)