Skip to content

Commit 3b358e9

Browse files
authored
Merge branch 'main' into ops
2 parents 8875bc5 + 4c54bab commit 3b358e9

Some content is hidden

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

57 files changed

+885
-484
lines changed

.ci/scripts/wheel/__init__.py

Whitespace-only changes.

.ci/scripts/wheel/envvar_linux.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
# This file is sourced into the environment before building a pip wheel. It
8+
# should typically only contain shell variable assignments. Be sure to export
9+
# any variables so that subprocesses will see them.
10+
11+
source "${GITHUB_WORKSPACE}/${REPOSITORY}/.ci/scripts/wheel/envvar_base.sh"

build/packaging/env_var_script_macos.sh renamed to .ci/scripts/wheel/envvar_macos.sh

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,7 @@
88
# should typically only contain shell variable assignments. Be sure to export
99
# any variables so that subprocesses will see them.
1010

11-
# Enable pybindings so that users can execute ExecuTorch programs from python.
12-
export EXECUTORCH_BUILD_PYBIND=1
13-
14-
# Ensure that CMAKE_ARGS is defined before referencing it. Defaults to empty
15-
# if not defined.
16-
export CMAKE_ARGS="${CMAKE_ARGS:-}"
17-
18-
# Link the XNNPACK backend into the pybindings runtime so that users can execute
19-
# ExecuTorch programs that delegate to it.
20-
CMAKE_ARGS="${CMAKE_ARGS} -DEXECUTORCH_BUILD_XNNPACK=ON"
11+
source "${GITHUB_WORKSPACE}/${REPOSITORY}/.ci/scripts/wheel/envvar_base.sh"
2112

2213
# When building for macOS, link additional backends into the pybindings runtime.
2314
CMAKE_ARGS="${CMAKE_ARGS} -DEXECUTORCH_BUILD_COREML=ON"

build/packaging/pre_build_script.sh renamed to .ci/scripts/wheel/pre_build_script.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ set -euxo pipefail
1414
# which does install them. Though we'd need to disable build isolation to be
1515
# able to see the installed torch package.
1616

17-
pip install --progress-bar off -r requirements-dev.txt
17+
"${GITHUB_WORKSPACE}/${REPOSITORY}/install_requirements.sh"

.ci/scripts/wheel/test_base.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
import os
8+
import subprocess
9+
import sys
10+
from dataclasses import dataclass
11+
from functools import cache
12+
from typing import List
13+
14+
15+
@cache
16+
def _unsafe_get_env(key: str) -> str:
17+
value = os.getenv(key)
18+
if value is None:
19+
raise RuntimeError(f"environment variable '{key}' is not set")
20+
return value
21+
22+
23+
@cache
24+
def _repository_root_dir() -> str:
25+
return os.path.join(
26+
_unsafe_get_env("GITHUB_WORKSPACE"),
27+
_unsafe_get_env("REPOSITORY"),
28+
)
29+
30+
31+
# For some reason, we are unable to see the entire repo in the python path.
32+
# So manually add it.
33+
sys.path.append(_repository_root_dir())
34+
from examples.models import Backend, Model
35+
36+
37+
@dataclass
38+
class ModelTest:
39+
model: Model
40+
backend: Backend
41+
42+
43+
def run_tests(model_tests: List[ModelTest]) -> None:
44+
# Why are we doing this envvar shenanigans? Since we build the testers, which
45+
# uses buck, we cannot run as root. This is a sneaky of getting around that
46+
# test.
47+
#
48+
# This can be reverted if either:
49+
# - We remove usage of buck in our builds
50+
# - We stop running the Docker image as root: https://github.com/pytorch/test-infra/issues/5091
51+
envvars = os.environ.copy()
52+
envvars.pop("HOME")
53+
54+
for model_test in model_tests:
55+
subprocess.run(
56+
[
57+
os.path.join(_repository_root_dir(), ".ci/scripts/test_model.sh"),
58+
str(model_test.model),
59+
# What to build `executor_runner` with for testing.
60+
"cmake",
61+
str(model_test.backend),
62+
],
63+
env=envvars,
64+
check=True,
65+
cwd=_repository_root_dir(),
66+
)

.ci/scripts/wheel/test_linux.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env python
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+
8+
import test_base
9+
from examples.models import Backend, Model
10+
11+
if __name__ == "__main__":
12+
test_base.run_tests(
13+
model_tests=[
14+
test_base.ModelTest(
15+
model=Model.Mv3,
16+
backend=Backend.XnnpackQuantizationDelegation,
17+
)
18+
]
19+
)

.ci/scripts/wheel/test_macos.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env python
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+
8+
import test_base
9+
from examples.models import Backend, Model
10+
11+
if __name__ == "__main__":
12+
test_base.run_tests(
13+
model_tests=[
14+
test_base.ModelTest(
15+
model=Model.Mv3,
16+
backend=Backend.XnnpackQuantizationDelegation,
17+
)
18+
]
19+
)

.github/workflows/_android.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
# Build LLM Demo for Android
3232
export BUILD_AAR_DIR=aar-out
3333
bash build/build_android_library.sh ${ARTIFACTS_DIR_NAME}
34-
bash build/build_android_instrumentation.sh ${ARTIFACTS_DIR_NAME}
34+
bash .ci/scripts/build_android_instrumentation.sh ${ARTIFACTS_DIR_NAME}
3535
3636
mkdir -p ${ARTIFACTS_DIR_NAME}/fp32-xnnpack-custom
3737
bash ".ci/scripts/test_llama.sh" -model stories110M -build_tool cmake -dtype fp16 -mode portable -upload ${ARTIFACTS_DIR_NAME}/fp32-xnnpack-custom

.github/workflows/build-wheels-linux.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ name: Build Linux Wheels
44
on:
55
pull_request:
66
paths:
7-
- build/packaging/**
7+
- .ci/**/*
88
- .github/workflows/build-wheels-linux.yml
99
push:
1010
branches:
@@ -39,9 +39,9 @@ jobs:
3939
matrix:
4040
include:
4141
- repository: pytorch/executorch
42-
pre-script: build/packaging/pre_build_script.sh
43-
post-script: build/packaging/post_build_script.sh
44-
smoke-test-script: build/packaging/smoke_test.py
42+
pre-script: .ci/scripts/wheel/pre_build_script.sh
43+
post-script: .ci/scripts/wheel/post_build_script.sh
44+
smoke-test-script: .ci/scripts/wheel/test_linux.py
4545
package-name: executorch
4646
name: ${{ matrix.repository }}
4747
uses: pytorch/test-infra/.github/workflows/build_wheels_linux.yml@main
@@ -51,11 +51,8 @@ jobs:
5151
test-infra-repository: pytorch/test-infra
5252
test-infra-ref: main
5353
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
54-
# ExecuTorch only needs the first layer of submodules; override the
55-
# "recursive" default to do less work, and to give the buck daemon fewer
56-
# files to look at.
57-
submodules: true
58-
env-var-script: build/packaging/env_var_script_linux.sh
54+
submodules: recursive
55+
env-var-script: .ci/scripts/wheel/envvar_linux.sh
5956
pre-script: ${{ matrix.pre-script }}
6057
post-script: ${{ matrix.post-script }}
6158
package-name: ${{ matrix.package-name }}

.github/workflows/build-wheels-macos.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ name: Build macOS Wheels
44
on:
55
pull_request:
66
paths:
7-
- build/packaging/**
7+
- .ci/**/*
88
- .github/workflows/build-wheels-macos.yml
99
push:
1010
branches:
@@ -39,9 +39,9 @@ jobs:
3939
matrix:
4040
include:
4141
- repository: pytorch/executorch
42-
pre-script: build/packaging/pre_build_script.sh
43-
post-script: build/packaging/post_build_script.sh
44-
smoke-test-script: build/packaging/smoke_test.py
42+
pre-script: .ci/scripts/wheel/pre_build_script.sh
43+
post-script: .ci/scripts/wheel/post_build_script.sh
44+
smoke-test-script: .ci/scripts/wheel/test_macos.py
4545
package-name: executorch
4646
name: ${{ matrix.repository }}
4747
uses: pytorch/test-infra/.github/workflows/build_wheels_macos.yml@main
@@ -51,12 +51,9 @@ jobs:
5151
test-infra-repository: pytorch/test-infra
5252
test-infra-ref: main
5353
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
54-
# ExecuTorch only needs the first layer of submodules; override the
55-
# "recursive" default to do less work, and to give the buck daemon fewer
56-
# files to look at.
57-
submodules: true
54+
submodules: recursive
5855
delocate-wheel: false
59-
env-var-script: build/packaging/env_var_script_macos.sh
56+
env-var-script: .ci/scripts/wheel/envvar_macos.sh
6057
pre-script: ${{ matrix.pre-script }}
6158
post-script: ${{ matrix.post-script }}
6259
package-name: ${{ matrix.package-name }}

.lintrunner.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,29 @@ init_command = [
343343
'--dry-run={{DRYRUN}}',
344344
'--requirement=requirements-lintrunner.txt',
345345
]
346+
347+
[[linter]]
348+
code = 'LICENSELINT'
349+
include_patterns = [
350+
'**/*',
351+
]
352+
exclude_patterns = [
353+
'**/fb/**',
354+
'.lintrunner.toml',
355+
]
356+
command = [
357+
'python',
358+
'-m',
359+
'lintrunner_adapters',
360+
'run',
361+
'grep_linter',
362+
'--pattern=Confidential and proprietary',
363+
'--linter-name=LICENSELINT',
364+
'--error-name=Wrong license',
365+
"""--error-description=\
366+
Code contributed to ExecuTorch open source repo should have \
367+
BSD-license header \
368+
""",
369+
'--',
370+
'@{{PATHSFILE}}',
371+
]

backends/arm/ethosu_backend.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
# debug functionality
2525
logger = logging.getLogger(__name__)
26+
logger.setLevel(logging.WARNING)
2627

2728

2829
@final

backends/arm/operator_support/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
pool_2d_support,
1212
reduce_sum_support,
1313
right_shift_support,
14+
slice_copy_support,
1415
to_copy_support,
1516
tosa_supported_operators,
1617
)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2025 Arm Limited and/or its affiliates.
2+
#
3+
# This source code is licensed under the BSD-style license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
6+
7+
import logging
8+
9+
import torch.fx as fx
10+
from executorch.backends.arm.operator_support.tosa_supported_operators import (
11+
register_tosa_support_check,
12+
SupportedTOSAOperatorCheck,
13+
)
14+
from executorch.backends.arm.tosa_specification import TosaSpecification
15+
from executorch.backends.arm.tosa_utils import getNodeArgs
16+
from executorch.exir.dialects._ops import ops as exir_ops
17+
18+
logger = logging.getLogger(__name__)
19+
logger.setLevel(logging.WARNING)
20+
21+
22+
@register_tosa_support_check
23+
class SliceCopySupported(SupportedTOSAOperatorCheck):
24+
targets = [exir_ops.edge.aten.slice_copy.Tensor]
25+
26+
tosa_specs = [
27+
TosaSpecification.create_from_string("TOSA-0.80+BI"),
28+
TosaSpecification.create_from_string("TOSA-0.80+MI"),
29+
]
30+
31+
def is_node_tosa_supported(self, node: fx.Node, tosa_spec: TosaSpecification) -> bool: # type: ignore[override, misc]
32+
if tosa_spec not in self.tosa_specs:
33+
return False
34+
35+
inputs = getNodeArgs(node)
36+
if len(inputs) == 5 and (step := inputs[4].number) != 1:
37+
logging.warning(f"{node.target} with step size of {step} not supported.")
38+
return False
39+
return True

backends/arm/operator_support/tosa_supported_operators.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ def register_tosa_support_check(checker: Type[SupportedTOSAOperatorCheck]):
7575
def get_registered_tosa_support_checks(
7676
tosa_spec: TosaSpecification,
7777
) -> list[Type[SupportedTOSAOperatorCheck]]:
78-
7978
if tosa_spec not in _tosa_spec_support:
8079
raise RuntimeError(
8180
f"TOSA specification not valid: {tosa_spec} not in {list(_tosa_spec_support.keys())}"
@@ -165,7 +164,6 @@ def is_node_supported(
165164
exir_ops.edge.aten._softmax.default,
166165
exir_ops.edge.aten.select_copy.int,
167166
exir_ops.edge.aten._log_softmax.default,
168-
exir_ops.edge.aten.slice_copy.Tensor,
169167
exir_ops.edge.aten.sub.Tensor,
170168
exir_ops.edge.aten.tanh.default,
171169
exir_ops.edge.aten.upsample_nearest2d.vec,

backends/arm/operators/op_add.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ def define_node(
4545
# Handle int8 (quantized) and int32
4646
assert inputs[0].dtype in [ts.DType.INT8, ts.DType.INT32]
4747

48+
dim_order = (
49+
inputs[0].dim_order
50+
if len(inputs[0].shape) > len(inputs[1].shape)
51+
else inputs[1].dim_order
52+
)
53+
4854
if inputs[0].dtype == ts.DType.INT8:
4955
rescaled_inputs, scale_back = tqutils.insert_rescale_ops_to_int32(
5056
tosa_graph, inputs, node
@@ -61,13 +67,14 @@ def define_node(
6167
# output.dtype == ts.DType.INT32
6268
add_output = output
6369

70+
input1, input2 = tutils.reshape_for_broadcast(
71+
tosa_graph, rescaled_inputs, dim_order
72+
)
73+
6474
# Do the INT32 Add
6575
tosa_graph.addOperator(
6676
TosaOp.Op().ADD,
67-
[
68-
rescaled_inputs[0].name,
69-
rescaled_inputs[1].name,
70-
],
77+
[input1.name, input2.name],
7178
[add_output.name],
7279
None,
7380
)
@@ -108,10 +115,12 @@ def define_node(
108115
assert inputs[0].dtype == ts.DType.FP32
109116
assert output.dtype == ts.DType.FP32
110117

118+
input1, input2 = tutils.reshape_for_broadcast(tosa_graph, inputs)
119+
111120
# MI lowering
112121
tosa_graph.addOperator(
113122
TosaOp.Op().ADD,
114-
[inputs[0].name, inputs[1].name],
123+
[input1.name, input2.name],
115124
[output.name],
116125
None,
117126
)

0 commit comments

Comments
 (0)