Skip to content

Commit b1b777c

Browse files
committed
Update on "Dtype selective build: enable in fbcode"
^ By removing `header_namespace` and depending on #include "selected_op_variants.h" instead of the full path #include <executorch/kernels/portable/cpu/selected_op_variants.h> Note: expose_operator_symbols=False only works in xplat, so add a failure message for that too. I don't think we should recommend for users to set it to true, as it prevents a library from linking multiple executorch_generated_libs (symbols will clash). Differential Revision: [D75082395](https://our.internmc.facebook.com/intern/diff/D75082395/) [ghstack-poisoned]
2 parents 35749c8 + 8543e6a commit b1b777c

File tree

118 files changed

+1849
-1306
lines changed

Some content is hidden

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

118 files changed

+1849
-1306
lines changed

.ci/scripts/tests/test_gather_benchmark_configs.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ def test_skip_disabled_configs(self):
5353
"mv3": [
5454
self.gather_benchmark_configs.DisabledConfig(
5555
config_name="disabled_config1",
56-
github_issue="https://github.com/org/repo/issues/123",
56+
github_issue="https://github.com/org/repo/issues/123", # @lint-ignore
5757
),
5858
self.gather_benchmark_configs.DisabledConfig(
5959
config_name="disabled_config2",
60-
github_issue="https://github.com/org/repo/issues/124",
60+
github_issue="https://github.com/org/repo/issues/124", # @lint-ignore
6161
),
6262
]
6363
},
@@ -84,7 +84,9 @@ def test_skip_disabled_configs(self):
8484
self.assertIn("enabled_config2", result)
8585

8686
def test_disabled_configs_have_github_links(self):
87-
github_issue_regex = re.compile(r"https://github\.com/.+/.+/issues/\d+")
87+
github_issue_regex = re.compile(
88+
r"https://github\.com/.+/.+/issues/\d+" # @lint-ignore
89+
)
8890

8991
for (
9092
model_name,

.ci/scripts/unittest-linux.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ if [[ "$BUILD_TOOL" == "cmake" ]]; then
2020
# Setup swiftshader and Vulkan SDK which are required to build the Vulkan delegate
2121
source .ci/scripts/setup-vulkan-linux-deps.sh
2222

23+
# We need the runner to test the built library.
2324
PYTHON_EXECUTABLE=python \
24-
CMAKE_ARGS="-DEXECUTORCH_BUILD_PYBIND=ON -DEXECUTORCH_BUILD_XNNPACK=ON -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON" \
25+
CMAKE_ARGS="-DEXECUTORCH_BUILD_EXECUTOR_RUNNER=ON -DEXECUTORCH_BUILD_TESTS=ON" \
2526
.ci/scripts/setup-linux.sh "$@"
2627

2728
.ci/scripts/unittest-linux-cmake.sh

.ci/scripts/unittest-macos.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ export PATH="${TMP_DIR}:$PATH"
2020
trap 'rm -rfv ${TMP_DIR}' EXIT
2121

2222
# Setup MacOS dependencies as there is no Docker support on MacOS atm
23+
# We need the runner to test the built library.
2324
PYTHON_EXECUTABLE=python \
24-
CMAKE_ARGS="-DEXECUTORCH_BUILD_PYBIND=ON -DEXECUTORCH_BUILD_COREML=ON -DEXECUTORCH_BUILD_MPS=ON -DEXECUTORCH_BUILD_XNNPACK=ON -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON" \
25+
CMAKE_ARGS="-DEXECUTORCH_BUILD_EXECUTOR_RUNNER=ON -DEXECUTORCH_BUILD_TESTS=ON" \
2526
${CONDA_RUN} --no-capture-output \
2627
.ci/scripts/setup-macos.sh "$@"
2728

.ci/scripts/wheel/envvar_base.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,3 @@
1111
# Ensure that CMAKE_ARGS is defined before referencing it. Defaults to empty
1212
# if not defined.
1313
export CMAKE_ARGS="${CMAKE_ARGS:-}"
14-
15-
# Link the XNNPACK backend into the pybindings runtime so that users can execute
16-
# ExecuTorch programs that delegate to it.
17-
CMAKE_ARGS="${CMAKE_ARGS} -DEXECUTORCH_BUILD_PYBIND=ON -DEXECUTORCH_BUILD_XNNPACK=ON"

.ci/scripts/wheel/envvar_macos.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,3 @@
99
# any variables so that subprocesses will see them.
1010

1111
source "${GITHUB_WORKSPACE}/${REPOSITORY}/.ci/scripts/wheel/envvar_base.sh"
12-
13-
# When building for macOS, link additional backends into the pybindings runtime.
14-
CMAKE_ARGS="${CMAKE_ARGS} -DEXECUTORCH_BUILD_COREML=ON"
15-
CMAKE_ARGS="${CMAKE_ARGS} -DEXECUTORCH_BUILD_MPS=ON"

.github/scripts/label_utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ def get_last_page_num_from_header(header: Any) -> int:
5151
# rel="next", <https://api.github.com/repositories/65600975/labels?per_page=100&page=3>; rel="last"
5252
link_info = header["link"]
5353
# Docs does not specify that it should be present for projects with just few labels
54-
# And https://github.com/malfet/deleteme/actions/runs/7334565243/job/19971396887 it's not the case
5554
if link_info is None:
5655
return 1
5756
prefix = "&page="

.github/scripts/test_extract_benchmark_results.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ def get_mock_happy_flow_content(app_type: str = "IOS_APP"):
2929
"name": "Syslog",
3030
"type": "DEVICE_LOG",
3131
"extension": "syslog",
32-
"url": "https://job_arn_1_device_log",
33-
"s3_url": "https://job_arn_1/test-workflow1/1/syslog.syslog",
32+
"url": "https://job_arn_1_device_log", # @lint-ignore
33+
"s3_url": "https://job_arn_1/test-workflow1/1/syslog.syslog", # @lint-ignore
3434
"app_type": app_type,
3535
"job_name": "job_arn_1_name",
3636
"os": "14",
@@ -55,8 +55,8 @@ def get_mock_happy_flow_content(app_type: str = "IOS_APP"):
5555
"name": "Customer Artifacts",
5656
"type": "CUSTOMER_ARTIFACT",
5757
"extension": "zip",
58-
"url": "https://job_arn_1_customer_artifact",
59-
"s3_url": "https://job_arn_1_customer_artifact1",
58+
"url": "https://job_arn_1_customer_artifact", # @lint-ignore
59+
"s3_url": "https://job_arn_1_customer_artifact1", # @lint-ignore
6060
"app_type": app_type,
6161
"job_name": "job_arn_1_device_name",
6262
"os": "14",
@@ -68,8 +68,8 @@ def get_mock_happy_flow_content(app_type: str = "IOS_APP"):
6868
"name": "Syslog",
6969
"type": "DEVICE_LOG",
7070
"extension": "syslog",
71-
"url": "https://job_arn_1_device_log",
72-
"s3_url": "https://job_arn_1/test-workflow1/1/syslog.syslog",
71+
"url": "https://job_arn_1_device_log", # @lint-ignore
72+
"s3_url": "https://job_arn_1/test-workflow1/1/syslog.syslog", # @lint-ignore
7373
"app_type": app_type,
7474
"job_name": "job_arn_2_name",
7575
"os": "14",
@@ -94,8 +94,8 @@ def get_mock_happy_flow_content(app_type: str = "IOS_APP"):
9494
"name": "Customer Artifacts",
9595
"type": "CUSTOMER_ARTIFACT",
9696
"extension": "zip",
97-
"url": "https://job_arn_1_customer_artifact",
98-
"s3_url": "https://job_arn_1_customer_artifact1",
97+
"url": "https://job_arn_1_customer_artifact", # @lint-ignore
98+
"s3_url": "https://job_arn_1_customer_artifact1", # @lint-ignore
9999
"app_type": app_type,
100100
"job_name": "job_arn_2_name",
101101
"os": "14",

.github/scripts/trymerge.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1964,7 +1964,7 @@ def check_for_sev(org: str, project: str, skip_mandatory_checks: bool) -> None:
19641964
response = cast(
19651965
Dict[str, Any],
19661966
gh_fetch_json_list(
1967-
"https://api.github.com/search/issues",
1967+
"https://api.github.com/search/issues", # @lint-ignore
19681968
params={"q": f'repo:{org}/{project} is:open is:issue label:"ci: sev"'},
19691969
),
19701970
)

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,19 @@ xcuserdata/
4040
.swiftpm/
4141
*.xcworkspace/
4242
*.xcframework/
43+
44+
# misc
45+
/.vscode/
46+
*.so
47+
*.dylib
48+
/cmake_wrapper.sh
49+
/data/
50+
/devtools/bundled_program/serialize/
51+
/exir/_serialize/program.fbs
52+
/exir/_serialize/scalar_type.fbs
53+
/include/
54+
/share/
55+
/version.py
56+
57+
# Android
58+
*.aar

.lintrunner.toml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,3 +378,48 @@ command = [
378378
'--',
379379
'@{{PATHSFILE}}',
380380
]
381+
382+
[[linter]]
383+
code = "TORCH_AO_IMPORT"
384+
include_patterns = ["**/*.py"]
385+
exclude_patterns = [
386+
"third-party/**",
387+
# TODO: remove exceptions as we migrate
388+
# backends
389+
"backends/arm/quantizer/**",
390+
"backends/arm/test/ops/**",
391+
"backends/vulkan/quantizer/**",
392+
"backends/vulkan/test/**",
393+
"backends/cadence/aot/quantizer/**",
394+
"backends/qualcomm/quantizer/**",
395+
"examples/qualcomm/**",
396+
"backends/xnnpack/quantizer/**",
397+
"backends/xnnpack/test/**",
398+
"exir/tests/test_passes.py",
399+
"extension/llm/export/builder.py",
400+
"extension/llm/export/quantizer_lib.py",
401+
"exir/tests/test_memory_planning.py",
402+
"backends/transforms/duplicate_dynamic_quant_chain.py",
403+
"exir/backend/test/demos/test_xnnpack_qnnpack.py",
404+
]
405+
406+
command = [
407+
"python3",
408+
"-m",
409+
"lintrunner_adapters",
410+
"run",
411+
"grep_linter",
412+
"--pattern=\\bfrom torch\\.ao\\.quantization\\.(?:quantizer|observer|quantize_pt2e|pt2e)(?:\\.[A-Za-z0-9_]+)*\\b",
413+
"--linter-name=TorchAOImport",
414+
"--error-name=Prohibited torch.ao.quantization import",
415+
"""--error-description=\
416+
Imports from torch.ao.quantization are not allowed. \
417+
Please import from torchao.quantization.pt2e instead.\n \
418+
* torchao.quantization.pt2e (includes all the utils, including observers, fake quants etc.) \n \
419+
* torchao.quantization.pt2e.quantizer (quantizer related objects and utils) \n \
420+
* torchao.quantization.pt2e.quantize_pt2e (prepare_pt2e, prepare_qat_pt2e, convert_pt2e) \n\n \
421+
If you need something from torch.ao.quantization, you can add your file to an exclude_patterns for TORCH_AO_IMPORT in .lintrunner.toml. \
422+
""",
423+
"--",
424+
"@{{PATHSFILE}}",
425+
]

.mypy.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,6 @@ ignore_missing_imports = True
9797

9898
[mypy-zstd]
9999
ignore_missing_imports = True
100+
101+
[mypy-torchao.*]
102+
follow_untyped_imports = True

CMakeLists.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,9 @@ add_library(executorch_core ${_executorch_core__srcs})
362362
add_library(executorch_no_prim_ops ALIAS executorch_core)
363363

364364
target_link_libraries(executorch_core PRIVATE program_schema)
365+
if(ANDROID)
366+
target_link_libraries(executorch_core PUBLIC log)
367+
endif()
365368
if(EXECUTORCH_USE_DL)
366369
# Check if dl exists for this toolchain and only then link it.
367370
find_library(DL_LIBRARY_EXISTS NAMES dl)
@@ -653,10 +656,6 @@ if(EXECUTORCH_BUILD_PYBIND)
653656
install(TARGETS portable_lib
654657
LIBRARY DESTINATION executorch/extension/pybindings
655658
)
656-
657-
if(EXECUTORCH_BUILD_EXTENSION_TRAINING)
658-
659-
endif()
660659
endif()
661660

662661
if(EXECUTORCH_BUILD_EXTENSION_TRAINING)

CMakePresets.json

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
{
2-
"version": 10,
3-
"cmakeMinimumRequired": {
4-
"major": 3,
5-
"minor": 31,
6-
"patch": 0
7-
},
8-
"$comment": "On-device AI across mobile, embedded and edge for PyTorch.",
2+
"version": 6,
93
"configurePresets": [
104
{
115
"name": "common",
126
"hidden": true,
13-
"binaryDir": "${sourceDir}/cmake-out",
14-
"generator": "Unix Makefiles"
7+
"binaryDir": "${sourceDir}/cmake-out"
158
},
169
{
1710
"name": "macos-arm64",

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ for basics.
420420
- Use [this](docs/source/backend-delegates-integration.md) guide when
421421
integrating your delegate with ExecuTorch.
422422
- Refer to [this](docs/source/backend-delegates-dependencies.md) set of
423-
guidelines when including a third-party depenency for your delegate.
423+
guidelines when including a third-party dependency for your delegate.
424424

425425
&nbsp;
426426

backends/apple/coreml/test/test_coreml_quantizer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
)
1616

1717
from executorch.backends.apple.coreml.quantizer import CoreMLQuantizer
18-
from torch.ao.quantization.quantize_pt2e import (
18+
from torch.export import export_for_training
19+
from torchao.quantization.pt2e.quantize_pt2e import (
1920
convert_pt2e,
2021
prepare_pt2e,
2122
prepare_qat_pt2e,
2223
)
23-
from torch.export import export_for_training
2424

2525

2626
class TestCoreMLQuantizer:

backends/arm/_passes/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from .convert_any_default_dim_dims_pass import ConvertAnyDefaultDimDimsPass # noqa
1616
from .convert_expand_copy_to_repeat import ConvertExpandCopyToRepeatPass # noqa
1717
from .convert_full_like_to_full_pass import ConvertFullLikeToFullPass # noqa
18+
from .convert_int_pow_to_mul import ConvertIntPowToMuls # noqa
1819
from .convert_minmax_pass import ConvertMinMaxPass # noqa
1920
from .convert_split_to_slice import ConvertSplitToSlicePass # noqa
2021
from .convert_squeezes_to_view import ConvertSqueezesToViewPass # noqa

backends/arm/_passes/arm_pass_manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
ConvertAnyDefaultDimDimsPass,
1919
ConvertExpandCopyToRepeatPass,
2020
ConvertFullLikeToFullPass,
21+
ConvertIntPowToMuls,
2122
ConvertMinMaxPass,
2223
ConvertMmToBmmPass,
2324
ConvertSplitToSlicePass,
@@ -131,14 +132,14 @@ def _tosa_080_BI_pipeline(self, exported_program: ExportedProgram) -> GraphModul
131132

132133
def _tosa_080_MI_pipeline(self, exported_program: ExportedProgram) -> GraphModule:
133134
self.add_pass(DecomposeSqrtPass())
135+
self.add_pass(ConvertIntPowToMuls())
134136
self.add_pass(ReplaceScalarWithTensorArgPassTOSAMI())
135137
self.add_pass(FuseQuantizedActivationPass())
136138
self.add_pass(RemoveGetItemPass())
137139
self.add_pass(ConvertSplitToSlicePass())
138140
self.add_pass(FuseBatchnorm2DPass(exported_program))
139141
self.add_pass(ConvertMmToBmmPass())
140142
self.add_pass(DecomposeLinearPass())
141-
self.add_pass(DecomposeLinearVectorNormPass())
142143
self.add_pass(DecomposeLeakyReLUPass())
143144
self.add_pass(DecomposeBatchNormPass())
144145
self.add_pass(DecomposeLayerNormPass())
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
# pyre-unsafe
7+
8+
from executorch.backends.arm._passes import ArmPass
9+
from executorch.exir.dialects._ops import ops as exir_ops
10+
11+
12+
class ConvertIntPowToMuls(ArmPass):
13+
"""
14+
Replaces pow with integer exponent with a series of multiplications.
15+
Only handles pow.Tensor_Scalar and not pow.Tensor_Tensor.
16+
Needs to be run before doing scalar to tensor conversion.
17+
"""
18+
19+
def call_operator(self, op, args, kwargs, meta):
20+
if op != exir_ops.edge.aten.pow.Tensor_Scalar:
21+
return super().call_operator(op, args, kwargs, meta)
22+
23+
x = args[0]
24+
exp = args[1]
25+
26+
# Handle zero first and return early
27+
if exp == 0:
28+
# return a tensor of ones with the same shape as x
29+
return super().call_operator(
30+
exir_ops.edge.aten.full_like.default, (x, 1), {}, meta, True
31+
)
32+
33+
if not isinstance(exp, int):
34+
return super().call_operator(op, args, kwargs, meta)
35+
36+
# Handle negative exponent
37+
if exp < 0:
38+
x = super().call_operator(
39+
exir_ops.edge.aten.reciprocal.default, (x,), {}, meta, True
40+
)
41+
exp = -exp
42+
43+
res = x
44+
45+
# Consider exponentiation by squaring, if exp turns out to be large.
46+
# Now we just roll out the multiplications.
47+
for _ in range(exp - 1):
48+
res = super().call_operator(
49+
exir_ops.edge.aten.mul.Tensor, (res, x), {}, meta, True
50+
)
51+
52+
return res

0 commit comments

Comments
 (0)