Skip to content

Commit 0bd635e

Browse files
mansnilsperheldArmRyan
authored
Arm backend: Add pypi package install option for VGF backend (#15551)
New setup option is added: --install-mlsdk-deps-with-pip For Linux/Windows x86 machines, PyPi packages of MLSDK repository for VGF backend may be used. This will eventually be the default. Reason it is not yet default is because of a limitation of model-converter to handle large models. The new option will decrease setup time, which can enable VGF backend testing in github. Co-authored-by: Per Held <[per.held@arm.com](mailto:per.held@arm.com)>, Ryan O'Shea <[ryan.oshea3@arm.com](mailto:ryan.oshea3@arm.com)> cc @freddan80 @per @zingo @oscarandersson8218 @digantdesai Signed-off-by: Måns Nilsson <mans.nilsson@arm.com> Co-authored-by: Per Held <per.held@arm.com> Co-authored-by: Per Held <per.held@arm.com>, Ryan O'Shea <ryan.oshea3@arm.com>
1 parent 2ad34b2 commit 0bd635e

File tree

8 files changed

+222
-32
lines changed

8 files changed

+222
-32
lines changed

backends/arm/CMakeLists.txt

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,44 @@ endif()
4848

4949
# VGF backend builds
5050
if(EXECUTORCH_BUILD_VGF)
51-
52-
# include libvgf
53-
set(LIBVGF_PATH
54-
"${EXECUTORCH_ROOT}/examples/arm/ethos-u-scratch/ml-sdk-for-vulkan-manifest/sw/vgf-lib/"
55-
)
56-
5751
set(VULKAN_THIRD_PARTY_PATH ${EXECUTORCH_ROOT}/backends/vulkan/third-party)
5852
set(VULKAN_HEADERS_PATH ${VULKAN_THIRD_PARTY_PATH}/Vulkan-Headers/include)
5953
set(VOLK_HEADERS_PATH ${VULKAN_THIRD_PARTY_PATH}/volk)
6054

61-
set(LIBVGF_STATIC "${LIBVGF_PATH}/build/src/libvgf.a")
55+
if(APPLE
56+
OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$"
57+
OR EXISTS
58+
"${EXECUTORCH_ROOT}/examples/arm/ethos-u-scratch/ml-sdk-for-vulkan-manifest/"
59+
)
60+
message(STATUS "libvgf sourced from local scratch tree")
61+
62+
# Legacy layout: libvgf sourced from local scratch tree
63+
set(LIBVGF_PATH
64+
"${EXECUTORCH_ROOT}/examples/arm/ethos-u-scratch/ml-sdk-for-vulkan-manifest/sw/vgf-lib/"
65+
)
66+
set(LIBVGF_STATIC "${LIBVGF_PATH}/build/src/libvgf.a")
67+
else()
68+
message(STATUS "libvgf installed from pip package")
69+
70+
set(Python3_FIND_VIRTUALENV FIRST)
71+
if(EXECUTORCH_ROOT AND EXISTS "${EXECUTORCH_ROOT}/env")
72+
set(Python3_EXECUTABLE "${EXECUTORCH_ROOT}/env/bin/python3")
73+
endif()
74+
75+
find_package(Python3 REQUIRED COMPONENTS Interpreter)
76+
77+
# Prefer arch-specific site-packages if present, else pure
78+
set(_vgf_site_arch "${Python3_SITEARCH}/vgf_lib/binaries")
79+
set(_vgf_site_pure "${Python3_SITELIB}/vgf_lib/binaries")
80+
if(EXISTS "${_vgf_site_arch}")
81+
set(LIBVGF_PATH "${_vgf_site_arch}")
82+
else()
83+
set(LIBVGF_PATH "${_vgf_site_pure}")
84+
endif()
85+
86+
set(LIBVGF_STATIC "${LIBVGF_PATH}/lib/libvgf.a")
87+
endif()
88+
6289
set(LIBVGF_INCLUDE "${LIBVGF_PATH}/include/")
6390

6491
add_library(vgf STATIC IMPORTED)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
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+
ai_ml_emulation_layer_for_vulkan == 0.7.0
7+
ai_ml_sdk_model_converter == 0.7.0
8+
ai_ml_sdk_vgf_library == 0.7.0

backends/arm/scripts/mlsdk_utils.sh

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,51 @@ function setup_path_emulation_layer() {
205205
model_emulation_layer_path="$(cd "${mlsdk_manifest_dir}/sw/emulation-layer/" && pwd)"
206206
prepend_env_in_setup_path LD_LIBRARY_PATH "${model_emulation_layer_path}/deploy/lib"
207207
prepend_env_in_setup_path DYLD_LIBRARY_PATH "${model_emulation_layer_path}/deploy/lib"
208+
prepend_env_in_setup_path VK_LAYER_PATH "${model_emulation_layer_path}/deploy/share/vulkan/explicit_layer.d"
208209
prepend_env_in_setup_path VK_INSTANCE_LAYERS VK_LAYER_ML_Tensor_Emulation
209210
prepend_env_in_setup_path VK_INSTANCE_LAYERS VK_LAYER_ML_Graph_Emulation
210-
prepend_env_in_setup_path VK_LAYER_PATH "${model_emulation_layer_path}/deploy/share/vulkan/explicit_layer.d"
211+
}
212+
213+
function setup_path_emulation_layer_from_pip() {
214+
if ! command -v emulation_layer >/dev/null 2>&1; then
215+
echo "[mlsdk_utils] 'emulation_layer' command not found; skipping pip emulation layer path setup"
216+
return
217+
fi
218+
219+
local output
220+
if ! output=$(emulation_layer 2>/dev/null); then
221+
echo "[mlsdk_utils] Failed to query emulation_layer environment; skipping"
222+
return
223+
fi
224+
225+
local exports
226+
exports=$(echo "$output" | grep '^export ' || true)
227+
228+
local ld_line
229+
ld_line=$(echo "$exports" | grep 'LD_LIBRARY_PATH=' || true)
230+
if [[ -n "${ld_line}" ]]; then
231+
local ld_value=${ld_line#export LD_LIBRARY_PATH=}
232+
ld_value=${ld_value%%:\$LD_LIBRARY_PATH*}
233+
if [[ -n "${ld_value}" ]]; then
234+
prepend_env_in_setup_path LD_LIBRARY_PATH "${ld_value}"
235+
fi
236+
fi
237+
238+
local vk_add_line
239+
vk_add_line=$(echo "$exports" | grep 'VK_ADD_LAYER_PATH=' || true)
240+
if [[ -n "${vk_add_line}" ]]; then
241+
local vk_add_value=${vk_add_line#export VK_ADD_LAYER_PATH=}
242+
if [[ -n "${vk_add_value}" ]]; then
243+
prepend_env_in_setup_path VK_ADD_LAYER_PATH "${vk_add_value}"
244+
fi
245+
fi
246+
247+
local vk_instance_line
248+
vk_instance_line=$(echo "$exports" | grep 'VK_INSTANCE_LAYERS=' || true)
249+
if [[ -n "${vk_instance_line}" ]]; then
250+
local vk_instance_value=${vk_instance_line#export VK_INSTANCE_LAYERS=}
251+
if [[ -n "${vk_instance_value}" ]]; then
252+
prepend_env_in_setup_path VK_INSTANCE_LAYERS "${vk_instance_value}"
253+
fi
254+
fi
211255
}

backends/arm/scripts/run_vkml.sh

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,14 @@ if [[ -z ${model} ]]; then echo "Model name needs to be provided"; exit 1; fi
5050

5151
source ${setup_path_script}
5252

53-
# basic checks before we get started
54-
hash ${converter} \
55-
|| { echo "Could not find ${converter} on PATH, ${_setup_msg}"; exit 1; }
53+
if ! command -v "${converter}" >/dev/null 2>&1; then
54+
if command -v model_converter >/dev/null 2>&1; then
55+
converter="model_converter"
56+
fi
57+
fi
58+
59+
command -v "${converter}" >/dev/null 2>&1 \
60+
|| { echo "Could not find a model converter executable (tried model-converter, model_converter). ${_setup_msg}"; exit 1; }
5661

5762

5863

backends/arm/test/runner_utils.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from executorch.backends.arm.tosa.compile_spec import TosaCompileSpec
3232
from executorch.backends.arm.tosa.specification import Tosa_1_00, TosaSpecification
3333
from executorch.backends.arm.vgf import VgfCompileSpec
34+
from executorch.backends.arm.vgf.model_converter import find_model_converter_binary
3435
from executorch.exir import ExecutorchProgramManager, ExportedProgram
3536
from executorch.exir.lowered_backend_module import LoweredBackendModule
3637
from torch.fx.node import Node
@@ -678,11 +679,15 @@ def corstone320_installed() -> bool:
678679

679680

680681
def model_converter_installed() -> bool:
681-
cmd = ["model-converter", "--version"]
682+
model_converter = find_model_converter_binary()
683+
if model_converter is None:
684+
return False
685+
682686
try:
683-
_run_cmd(cmd, check=True)
684-
except:
687+
_run_cmd([model_converter, "--version"], check=True)
688+
except Exception:
685689
return False
690+
686691
return True
687692

688693

backends/arm/vgf/backend.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,24 @@
1717
import tempfile
1818
from typing import final, List
1919

20-
from executorch.backends.arm.tosa.backend import (
20+
from executorch.backends.arm.tosa.backend import ( # type: ignore[import-not-found]
2121
arm_get_first_delegation_tag,
2222
TOSABackend,
2323
)
24-
from executorch.backends.arm.vgf.compile_spec import VgfCompileSpec
25-
from executorch.exir.backend.backend_details import BackendDetails, PreprocessResult
26-
from executorch.exir.backend.compile_spec_schema import CompileSpec
24+
25+
from executorch.backends.arm.vgf.compile_spec import ( # type: ignore[import-not-found]
26+
VgfCompileSpec,
27+
)
28+
from executorch.backends.arm.vgf.model_converter import ( # type: ignore[import-not-found]
29+
require_model_converter_binary,
30+
)
31+
from executorch.exir.backend.backend_details import ( # type: ignore[import-not-found]
32+
BackendDetails,
33+
PreprocessResult,
34+
)
35+
from executorch.exir.backend.compile_spec_schema import ( # type: ignore[import-not-found]
36+
CompileSpec,
37+
)
2738
from torch.export.exported_program import ExportedProgram
2839

2940
# debug functionality
@@ -96,9 +107,10 @@ def vgf_compile(
96107
f.write(tosa_flatbuffer)
97108

98109
additional_flags = " ".join(compile_flags)
110+
converter_binary = require_model_converter_binary()
99111
vgf_path = tosa_path + ".vgf"
100112
conversion_command = (
101-
f"model-converter {additional_flags} -i {tosa_path} -o {vgf_path}"
113+
f"{converter_binary} {additional_flags} -i {tosa_path} -o {vgf_path}"
102114
)
103115
try:
104116
subprocess.run(
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
from __future__ import annotations
7+
8+
from shutil import which
9+
from typing import Optional
10+
11+
MODEL_CONVERTER_BINARY = "model-converter"
12+
_MODEL_CONVERTER_FALLBACK_BINARY = "model_converter"
13+
14+
15+
def find_model_converter_binary() -> Optional[str]:
16+
"""Return the name of the first model converter executable on PATH."""
17+
18+
for candidate in (MODEL_CONVERTER_BINARY, _MODEL_CONVERTER_FALLBACK_BINARY):
19+
if which(candidate):
20+
return candidate
21+
return None
22+
23+
24+
def require_model_converter_binary() -> str:
25+
"""Return a usable model converter executable or raise a helpful error."""
26+
27+
binary = find_model_converter_binary()
28+
if binary is None:
29+
tried = ", ".join((MODEL_CONVERTER_BINARY, _MODEL_CONVERTER_FALLBACK_BINARY))
30+
raise RuntimeError(
31+
"Unable to locate a model converter executable. "
32+
f"Tried: {tried}. Ensure the Model Converter is installed and on PATH."
33+
)
34+
return binary

examples/arm/setup.sh

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enable_model_converter=0 # model-converter tool for VGF output
2626
enable_vgf_lib=0 # vgf reader - runtime backend dependency
2727
enable_emulation_layer=0 # Vulkan layer driver - emulates Vulkan ML extensions
2828
enable_vulkan_sdk=0 # Download and export Vulkan SDK required by emulation layer
29+
enable_mlsdk_pip_install=0 # This is a temporary option that will soon be the default
2930

3031
# Figure out if setup.sh was called or sourced and save it into "is_script_sourced"
3132
(return 0 2>/dev/null) && is_script_sourced=1 || is_script_sourced=0
@@ -51,6 +52,7 @@ OPTION_LIST=(
5152
"--enable-emulation-layer Enable MLSDK Vulkan emulation layer"
5253
"--disable-ethos-u-deps Do not setup what is needed for Ethos-U"
5354
"--enable-mlsdk-deps Setup what is needed for MLSDK"
55+
"--install-mlsdk-deps-with-pip Use MLSDK PyPi package instead of building from source"
5456
"--mlsdk-manifest-url URL to the MLSDK manifest for vulkan."
5557
"--help Display help"
5658
)
@@ -140,6 +142,10 @@ function check_options() {
140142
enable_vela=0
141143
shift
142144
;;
145+
--install-mlsdk-deps-with-pip)
146+
enable_mlsdk_pip_install=1
147+
shift
148+
;;
143149
--enable-mlsdk-deps)
144150
enable_model_converter=1
145151
enable_vgf_lib=1
@@ -176,12 +182,22 @@ function setup_ethos_u_tools() {
176182
CMAKE_POLICY_VERSION_MINIMUM=3.5 BUILD_PYBIND=1 pip install --no-dependencies -r $et_dir/backends/arm/requirements-arm-ethos-u.txt
177183
}
178184

185+
function setup_mlsdk_dependencies() {
186+
log_step "mlsdk" "Installing MLSDK dependencies from pip"
187+
pip install -r $et_dir/backends/arm/requirements-arm-vgf.txt
188+
}
189+
179190
function create_setup_path(){
180191
cd "${root_dir}"
181192

182193
clear_setup_path
183194
log_step "path" "Generating setup path scripts at ${setup_path_script}"
184195

196+
local use_mlsdk_pip=0
197+
if use_mlsdk_pip_package; then
198+
use_mlsdk_pip=1
199+
fi
200+
185201
if [[ "${enable_fvps}" -eq 1 ]]; then
186202
setup_path_fvp
187203
fi
@@ -194,19 +210,48 @@ function create_setup_path(){
194210
setup_path_vulkan
195211
fi
196212

197-
if [[ "${enable_model_converter}" -eq 1 ]]; then
213+
if [[ "${enable_model_converter}" -eq 1 && "${use_mlsdk_pip}" -eq 0 ]]; then
198214
setup_path_model_converter
199215
fi
200216

201-
if [[ "${enable_vgf_lib}" -eq 1 ]]; then
217+
if [[ "${enable_vgf_lib}" -eq 1 && "${use_mlsdk_pip}" -eq 0 ]]; then
202218
setup_path_vgf_lib
203219
fi
204220

205221
if [[ "${enable_emulation_layer}" -eq 1 ]]; then
206-
setup_path_emulation_layer
222+
if [[ "${use_mlsdk_pip}" -eq 0 ]]; then
223+
setup_path_emulation_layer
224+
else
225+
setup_path_emulation_layer_from_pip
226+
fi
227+
fi
228+
229+
log_step "path" "Update PATH by sourcing ${setup_path_script}.{sh|fish}"
230+
}
231+
232+
function use_mlsdk_pip_package() {
233+
os=$(uname -s)
234+
arch=$(uname -m)
235+
236+
if [[ "${enable_mlsdk_pip_install}" -eq 0 ]]; then
237+
return 1
238+
fi
239+
240+
if [[ "$os" == "Darwin" ]]; then
241+
if [[ "${enable_mlsdk_pip_install}" -eq 1 ]]; then
242+
log_step "mlsdk" "[error] MLSDK pip install not yet supported on MacOS"
243+
exit 1
244+
fi
245+
fi
246+
247+
if [[ "$arch" == "arm64" || "$arch" == "aarch64" ]]; then
248+
if [[ "${enable_mlsdk_pip_install}" -eq 1 ]]; then
249+
log_step "mlsdk" "[error] MLSDK pip install not yet supported on aarch64"
250+
exit 1
251+
fi
207252
fi
208253

209-
log_step "path" "Update PATH by sourcing ${setup_path_script}.{sh|fish}"
254+
return 0
210255
}
211256

212257

@@ -224,6 +269,7 @@ if [[ $is_script_sourced -eq 0 ]]; then
224269
source $et_dir/backends/arm/scripts/fvp_utils.sh
225270
source $et_dir/backends/arm/scripts/toolchain_utils.sh
226271
source $et_dir/backends/arm/scripts/vulkan_utils.sh
272+
source $et_dir/backends/arm/scripts/mlsdk_utils.sh
227273

228274
log_step "main" "Checking platform and OS"
229275
check_platform_support
@@ -239,8 +285,12 @@ if [[ $is_script_sourced -eq 0 ]]; then
239285
mlsdk_manifest_dir="${root_dir}/${mlsdk_manifest_dir}"
240286
fi
241287

242-
log_step "options" "root=${root_dir}, target-toolchain=${target_toolchain:-<default>}, mlsdk-dir=${mlsdk_manifest_dir}"
243-
log_step "options" "ethos-u: fvps=${enable_fvps}, toolchain=${enable_baremetal_toolchain}, vela=${enable_vela} | mlsdk: model-converter=${enable_model_converter}, vgf-lib=${enable_vgf_lib}, emu-layer=${enable_emulation_layer}, vulkan-sdk=${enable_vulkan_sdk}"
288+
log_step "options" \
289+
"root=${root_dir}, target-toolchain=${target_toolchain:-<default>}, mlsdk-dir=${mlsdk_manifest_dir}"
290+
log_step "options" \
291+
"ethos-u: fvps=${enable_fvps}, toolchain=${enable_baremetal_toolchain}, vela=${enable_vela} | " \
292+
"mlsdk: model-converter=${enable_model_converter}, vgf-lib=${enable_vgf_lib}, " \
293+
"emu-layer=${enable_emulation_layer}, vulkan-sdk=${enable_vulkan_sdk}"
244294

245295
# Setup toolchain
246296
if [[ "${enable_baremetal_toolchain}" -eq 1 ]]; then
@@ -267,13 +317,18 @@ if [[ $is_script_sourced -eq 0 ]]; then
267317
if [[ "${enable_model_converter}" -eq 1 || \
268318
"${enable_vgf_lib}" -eq 1 || \
269319
"${enable_emulation_layer}" -eq 1 ]]; then
270-
log_step "mlsdk" "Configuring MLSDK components (model-converter=${enable_model_converter}, vgf-lib=${enable_vgf_lib}, emu-layer=${enable_emulation_layer})"
271-
source $et_dir/backends/arm/scripts/mlsdk_utils.sh
272-
setup_mlsdk "${root_dir}" \
273-
"${mlsdk_manifest_dir}" \
274-
"${enable_model_converter}" \
275-
"${enable_vgf_lib}" \
276-
"${enable_emulation_layer}"
320+
log_step "mlsdk" "Configuring MLSDK components (model-converter=${enable_model_converter}, " \
321+
"vgf-lib=${enable_vgf_lib}, emu-layer=${enable_emulation_layer})"
322+
if use_mlsdk_pip_package; then
323+
setup_mlsdk_dependencies
324+
else
325+
log_step "mlsdk" "Installing MLSDK dependencies from source"
326+
setup_mlsdk ${root_dir} \
327+
${mlsdk_manifest_dir} \
328+
${enable_model_converter} \
329+
${enable_vgf_lib} \
330+
${enable_emulation_layer}
331+
fi
277332
fi
278333

279334
# Create the setup_path.sh used to create the PATH variable for shell

0 commit comments

Comments
 (0)