From c23856b38b29c7eb46f7eb835e1767695fef5ed9 Mon Sep 17 00:00:00 2001 From: "riseproject-dev[bot]" <330740410+riseproject-dev[bot]@users.noreply.github.com> Date: Thu, 22 Oct 2026 12:00:25 +0000 Subject: [PATCH 1/5] executorch: Add versions 1.5.0, 1.5.1 Signed-off-by: riseproject-dev[bot] <330740410+riseproject-dev[bot]@users.noreply.github.com> --- docs/packages/executorch.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/packages/executorch.yaml b/docs/packages/executorch.yaml index fb148b98c445..635e147d4a2a 100644 --- a/docs/packages/executorch.yaml +++ b/docs/packages/executorch.yaml @@ -16,3 +16,5 @@ versions: - filename: executorch-1.4.1-cp314-cp314-manylinux_2_39_riscv64.whl sha256: 6cc15f5a4b2948289a4c0b4d86dd0202f903e8ac93e008c344a235312abf0bdc requires-python: <3.15,>=3.10 +- version: 1.5.0 +- version: 1.5.1 From 099fa63c560dbb4979631d56b0d2b4d980266a6b Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 02:20:45 +0800 Subject: [PATCH 2/5] executorch: Carry patches over to versions 1.5.0, 1.5.1 Rebased 0003 and 0004 (root CMakeLists.txt context moved upstream); 0001, 0002, 0005, 0006, 0007 are unchanged. --- ...de-vendored-third-party-licences-in-.patch | 34 ++++++ ...rce-directory-name-check-for-cibuild.patch | 65 ++++++++++ ...bind-extensions-as-MODULE-not-SHARED.patch | 115 ++++++++++++++++++ ...able_lib-SHARED-for-llm-runner-linka.patch | 79 ++++++++++++ ...-simd-arch-fatal-error-portable-fall.patch | 73 +++++++++++ ...ry-cpuinfo-uarchs-once-cpuinfo-is-in.patch | 73 +++++++++++ ...back-to-the-online-CPU-count-when-cp.patch | 63 ++++++++++ 7 files changed, 502 insertions(+) create mode 100644 patches/executorch/1.5.0/0001-packaging-Include-vendored-third-party-licences-in-.patch create mode 100644 patches/executorch/1.5.0/0002-cmake-relax-source-directory-name-check-for-cibuild.patch create mode 100644 patches/executorch/1.5.0/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch create mode 100644 patches/executorch/1.5.0/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch create mode 100644 patches/executorch/1.5.0/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch create mode 100644 patches/executorch/1.5.0/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch create mode 100644 patches/executorch/1.5.0/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch diff --git a/patches/executorch/1.5.0/0001-packaging-Include-vendored-third-party-licences-in-.patch b/patches/executorch/1.5.0/0001-packaging-Include-vendored-third-party-licences-in-.patch new file mode 100644 index 000000000000..7e65c08e10ed --- /dev/null +++ b/patches/executorch/1.5.0/0001-packaging-Include-vendored-third-party-licences-in-.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000001 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Thu, 10 Jul 2026 00:00:00 +0000 +Subject: [PATCH] packaging: Include vendored third-party licences in the + wheel + +The compiled extensions in this wheel statically link FP16, FXdiv, +XNNPACK, cpuinfo, pthreadpool, flatbuffers, flatcc, Eigen, pocketfft, +nlohmann/json and pybind11, but `license-files` only reaches the +project's own LICENSE. RISE distributes these wheels and must also +carry the licence of every statically linked dependency, so widen the +glob to pick up the `LICENSE.` files the riscv64 build stages at +the project root before `pip wheel` runs. + +Upstream-Status: Inappropriate [only relevant to a distributor bundling vendored third-party licences; reproduces identically on any architecture] + +Signed-off-by: RISE Project CI +--- + pyproject.toml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pyproject.toml b/pyproject.toml +index 0000000000..0000000000 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -100,7 +100,7 @@ + # package, and package_data to restrict the set up non-python files we + # include. See also setuptools/discovery.py for custom finders. + [tool.setuptools] +-license-files = ["LICENSE"] ++license-files = ["LICENSE", "LICENSE.*"] + + [tool.setuptools.package-dir] + # Tell setuptools to follow the symlink: src/executorch/* -> * for all first level diff --git a/patches/executorch/1.5.0/0002-cmake-relax-source-directory-name-check-for-cibuild.patch b/patches/executorch/1.5.0/0002-cmake-relax-source-directory-name-check-for-cibuild.patch new file mode 100644 index 000000000000..41e36734ac70 --- /dev/null +++ b/patches/executorch/1.5.0/0002-cmake-relax-source-directory-name-check-for-cibuild.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000002 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Thu, 10 Jul 2026 00:00:00 +0000 +Subject: [PATCH] cmake: stop requiring the checkout dir be named `executorch` + +CMakeLists.txt hard-fails configure unless the checkout's directory is +named exactly `executorch`, because `_common_include_directories` adds +the checkout's *parent* directory so in-tree code can say +`#include ` (upstream tracks lifting this +restriction at https://github.com/pytorch/executorch/issues/6475). + +cibuildwheel always mounts/copies the source into its manylinux +container at the fixed path `/project`, so this check always trips +there, regardless of what directory this repo is checked out to on the +runner. Provide the same `` include path through a +configure-time symlink instead of requiring a literally named parent +directory, so the build works unmodified under cibuildwheel. + +Upstream-Status: Inappropriate [only relevant to cibuildwheel, which always mounts the source at a fixed /project path inside its build container; see pytorch/executorch#6475] + +Signed-off-by: RISE Project CI +--- + CMakeLists.txt | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index be0cec2..4668d0a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -447,22 +447,20 @@ if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE + list(APPEND _common_compile_options $<$>:-fPIC>) + endif() + +-# Let files say "include ". +-# TODO(#6475): This requires/assumes that the repo lives in a directory named +-# exactly `executorch`. Check the assumption first. Remove this check once we +-# stop relying on the assumption. +-cmake_path(GET CMAKE_CURRENT_SOURCE_DIR FILENAME _repo_dir_name) +-if(NOT "${_repo_dir_name}" STREQUAL "executorch") +- message( +- FATAL_ERROR +- "The ExecuTorch repo must be cloned into a directory named exactly " +- "`executorch`; found `${_repo_dir_name}`. See " +- "https://github.com/pytorch/executorch/issues/6475 for progress on a " +- "fix for this restriction." ++# Let files say "include ", regardless of what ++# the checkout directory is actually named (see ++# https://github.com/pytorch/executorch/issues/6475). Provide that include ++# path unconditionally through a configure-time symlink, rather than ++# requiring the checkout itself be named `executorch`. ++set(_executorch_include_shim "${CMAKE_BINARY_DIR}/_executorch_include") ++file(MAKE_DIRECTORY "${_executorch_include_shim}") ++if(NOT EXISTS "${_executorch_include_shim}/executorch") ++ file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}" ++ "${_executorch_include_shim}/executorch" SYMBOLIC + ) + endif() + set(_common_include_directories +- $ ++ $ + $ + $ + $ +-- +2.34.1 diff --git a/patches/executorch/1.5.0/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch b/patches/executorch/1.5.0/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch new file mode 100644 index 000000000000..6819d082c2df --- /dev/null +++ b/patches/executorch/1.5.0/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000003 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Mon, 28 Sep 2026 00:00:00 +0000 +Subject: [PATCH] cmake: build pybind extensions as MODULE, not SHARED + +pybind11_add_module( SHARED ...) makes CMake's Python_add_library() +require the Python::Python target (COMPONENT Development.Embed) to exist +at configure time, even though strip_python_lib() immediately removes the +resulting Python::Python/pybind11::embed link dependency again -- these +are ordinary dlopen()'d extension modules that resolve Python symbols +from the running interpreter, never anything that embeds Python. + +Vanilla manylinux images (unlike the custom manylinux-builder images +PyTorch's own CI uses) ship only a static libpythonX.Y.a and never +satisfy Development.Embed, so find_package(Python) never defines +Python::Python and every pybind11_add_module(... SHARED ...) call fails +configure outright: + + CMake Error: Python_ADD_LIBRARY: dependent target 'Python::Python' is + not defined. Did you miss to request COMPONENT 'Development.Embed'? + +Dropping SHARED (the pybind11 default, MODULE) only requires +Development.Module, which these images do provide, and produces the +exact same importable extension: strip_python_lib()'s job of avoiding a +runtime libpython link was already redundant with MODULE all along. + +Upstream-Status: To upstream [not yet submitted; a real portability bug on any vanilla manylinux image lacking an embeddable libpython (Development.Embed), independent of riscv64 -- pytorch/executorch's own CI runs a custom manylinux-builder image that does provide one, so upstream has likely never hit this] + +Signed-off-by: RISE Project CI +--- + CMakeLists.txt | 4 ++-- + backends/apple/coreml/CMakeLists.txt | 2 +- + codegen/tools/CMakeLists.txt | 2 +- + extension/llm/runner/CMakeLists.txt | 2 +- + extension/training/CMakeLists.txt | 2 +- + 5 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 93e02c5..ac73707 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1397,7 +1397,7 @@ if(EXECUTORCH_BUILD_PYBIND) + endif() + + # pybind portable_lib +- pybind11_add_module(portable_lib SHARED extension/pybindings/pybindings.cpp) ++ pybind11_add_module(portable_lib extension/pybindings/pybindings.cpp) + strip_python_lib(portable_lib) + # The actual output file needs a leading underscore so it can coexist with + # portable_lib.py in the same python package. PyTorch requires C++20, so +@@ -1488,7 +1488,7 @@ if(EXECUTORCH_BUILD_PYBIND) + # pybind data_loader module - provides PyDataLoader type for external + # pybinding extensions to create custom data loaders + pybind11_add_module( +- data_loader SHARED extension/pybindings/pybindings_data_loader.cpp ++ data_loader extension/pybindings/pybindings_data_loader.cpp + ) + strip_python_lib(data_loader) + target_include_directories(data_loader PRIVATE ${_common_include_directories}) +diff --git a/backends/apple/coreml/CMakeLists.txt b/backends/apple/coreml/CMakeLists.txt +index 8df0cfd..fb07e6e 100644 +--- a/backends/apple/coreml/CMakeLists.txt ++++ b/backends/apple/coreml/CMakeLists.txt +@@ -181,7 +181,7 @@ install( + + if(EXECUTORCH_BUILD_PYBIND) + pybind11_add_module( +- executorchcoreml SHARED runtime/inmemoryfs/inmemory_filesystem_py.cpp ++ executorchcoreml runtime/inmemoryfs/inmemory_filesystem_py.cpp + runtime/inmemoryfs/inmemory_filesystem_utils.cpp + ) + strip_python_lib(executorchcoreml) +diff --git a/codegen/tools/CMakeLists.txt b/codegen/tools/CMakeLists.txt +index 143d2c1..d95716d 100644 +--- a/codegen/tools/CMakeLists.txt ++++ b/codegen/tools/CMakeLists.txt +@@ -8,7 +8,7 @@ + # Check if pybind11 is available + + # Create the selective_build pybind11 module +-pybind11_add_module(selective_build SHARED selective_build.cpp) ++pybind11_add_module(selective_build selective_build.cpp) + strip_python_lib(selective_build) + + # Set the output name to match the module name +diff --git a/extension/llm/runner/CMakeLists.txt b/extension/llm/runner/CMakeLists.txt +index 17016b9..110e252 100644 +--- a/extension/llm/runner/CMakeLists.txt ++++ b/extension/llm/runner/CMakeLists.txt +@@ -113,7 +113,7 @@ endif() + if(EXECUTORCH_BUILD_PYBIND) + # Create the Python extension module for LLM runners + pybind11_add_module( +- _llm_runner SHARED ${CMAKE_CURRENT_SOURCE_DIR}/pybindings.cpp ++ _llm_runner ${CMAKE_CURRENT_SOURCE_DIR}/pybindings.cpp + ) + strip_python_lib(_llm_runner) + +diff --git a/extension/training/CMakeLists.txt b/extension/training/CMakeLists.txt +index 7b76723..cabf478 100644 +--- a/extension/training/CMakeLists.txt ++++ b/extension/training/CMakeLists.txt +@@ -77,7 +77,7 @@ if(EXECUTORCH_BUILD_PYBIND) + endif() + + pybind11_add_module( +- _training_lib SHARED ++ _training_lib + ${CMAKE_CURRENT_SOURCE_DIR}/pybindings/_training_lib.cpp + ) + strip_python_lib(_training_lib) + +-- +2.34.1 + diff --git a/patches/executorch/1.5.0/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch b/patches/executorch/1.5.0/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch new file mode 100644 index 000000000000..370015c5cd67 --- /dev/null +++ b/patches/executorch/1.5.0/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000004 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Mon, 28 Sep 2026 00:00:00 +0000 +Subject: [PATCH] cmake: keep portable_lib SHARED for llm/runner linkage + +0003 converted all six pybind11_add_module( SHARED ...) call sites to +plain pybind11_add_module( ...) (MODULE), since vanilla manylinux +images never satisfy Python_add_library(SHARED)'s Python::Python +(Development.Embed) requirement. portable_lib is not like the other five, +though: extension/llm/runner/CMakeLists.txt does +target_link_libraries(_llm_runner PRIVATE ... portable_lib ...), and CMake +refuses to link a MODULE_LIBRARY into another target at all: + + CMake Error: Target "portable_lib" of type MODULE_LIBRARY may not be + linked into another target. One may link only to INTERFACE, OBJECT, + STATIC or SHARED libraries, or to executables with the ENABLE_EXPORTS + property set. + +This is a CMake generator restriction on the target type itself (checked in +every CMake version's link-dependency analysis), not something any +pybind11_add_module() argument can opt out of -- so portable_lib has to stay +SHARED, and the Development.Embed gap has to be closed some other way. + +FindPython's __Python_ADD_LIBRARY() (Modules/FindPython/Support.cmake) +requires the Python::Python target to already exist before it will even +add_library(... SHARED ...), and then links the new target against it: + + if (NOT type STREQUAL "MODULE" AND NOT TARGET ${prefix}::Python) + message (SEND_ERROR "...dependent target '${prefix}::Python' is not + defined. Did you miss to request COMPONENT 'Development.Embed'?") + ... + target_link_libraries (${name} PRIVATE ${prefix}::Python) + +Nothing requires that target to carry a real embeddable libpython, though: +defining Python::Python ourselves as a link-free INTERFACE IMPORTED target +when Development.Embed didn't find one satisfies the existence check, and +strip_python_lib() (already applied to portable_lib right below) then +removes Python::Python/pybind11::embed from portable_lib's real link line +exactly as it already does for the other five, now-MODULE targets -- so no +embeddable libpython is ever actually linked, and portable_lib comes out +identical to what it built as on upstream's own manylinux-builder CI, which +does have Development.Embed and never exercises this fallback. + +Upstream-Status: To upstream [not yet submitted; a real portability bug on any vanilla manylinux image lacking an embeddable libpython (Development.Embed), independent of riscv64, same as 0003] + +Signed-off-by: RISE Project CI +--- + CMakeLists.txt | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ac73707..c2bcca2 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1397,7 +1397,20 @@ if(EXECUTORCH_BUILD_PYBIND) + endif() + + # pybind portable_lib +- pybind11_add_module(portable_lib extension/pybindings/pybindings.cpp) ++ # Unlike the other five pybind11_add_module() call sites, portable_lib is ++ # itself target_link_libraries()'d into extension/llm/runner's _llm_runner, ++ # and CMake refuses to link a MODULE_LIBRARY into another target -- so this ++ # one has to stay SHARED. Python_add_library(SHARED) unconditionally ++ # requires a Python::Python target to already exist (Development.Embed), ++ # which vanilla manylinux images never provide; define it as a link-free ++ # stand-in when missing so the SHARED add_library() call is allowed to ++ # proceed. strip_python_lib() below removes it (and pybind11::embed) from ++ # portable_lib's real link line either way, so no embeddable libpython is ++ # ever actually required. ++ if(NOT TARGET Python::Python) ++ add_library(Python::Python INTERFACE IMPORTED) ++ endif() ++ pybind11_add_module(portable_lib SHARED extension/pybindings/pybindings.cpp) + strip_python_lib(portable_lib) + # The actual output file needs a leading underscore so it can coexist with + # portable_lib.py in the same python package. PyTorch requires C++20, so + +-- +2.34.1 diff --git a/patches/executorch/1.5.0/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch b/patches/executorch/1.5.0/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch new file mode 100644 index 000000000000..5ec70df461bd --- /dev/null +++ b/patches/executorch/1.5.0/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000005 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Mon, 28 Sep 2026 00:00:00 +0000 +Subject: [PATCH] cmake: drop FFHT SIMD arch fatal error, portable fallback exists + +extension/llm/custom_ops/CMakeLists.txt picks a vendored FFHT (Fast +Hadamard Transform) SIMD kernel source file to compile based on +CMAKE_SYSTEM_PROCESSOR -- fht_neon.c for aarch64/arm64/armv7, fht_avx.c for +x86_64/AMD64 -- and hard-errors for every other architecture, riscv64 +included: + + CMake Error: Unsupported CMAKE_SYSTEM_PROCESSOR riscv64. (If 32-bit x86, + try using fht_avx.c and send a PR if it works!) + +But nothing on such an architecture actually needs an FFHT SIMD kernel. +extension/llm/custom_ops/spinquant/fast_hadamard_transform.h's +fast_hadamard_transform_ffht_impl() -- the only caller of fht_float()/ +fht_double() outside the vendored FFHT sources themselves -- already +branches on the compiler-defined architecture macros, not +CMAKE_SYSTEM_PROCESSOR: + + #if defined(__aarch64__) || defined(__x86_64__) + fht_float(vec, log2_vec_size); + normalize_after_fht(vec, log2_vec_size); + #else + fast_hadamard_transform_simple_impl(vec, log2_vec_size); + #endif + +so on any architecture other than __aarch64__/__x86_64__ -- riscv64 +included -- the portable, scalar fast_hadamard_transform_simple_impl() is +already used at compile time, and the FFHT SIMD kernel's fht_float()/ +fht_double() symbols are never referenced, let alone linked. The +CMakeLists.txt FATAL_ERROR was refusing to configure over a source file +that would never have been needed. Replace it with a STATUS message and +add no FFHT source at all for these architectures; the vendored fht_avx.c/ +fht_neon.c/fht_sse.c/dumb_fht.c files use a different, narrower API +(void dumb_fht(float*, int) vs. fht_float()'s int fht_float(float*, int), +and no fht_double()/_oop equivalents) and were never a drop-in match +regardless of architecture. + +Upstream-Status: To upstream [not yet submitted; the FATAL_ERROR blocks every architecture outside x86_64/aarch64/armv7 even though fast_hadamard_transform.h already has a portable fallback that needs none of them, independent of riscv64] + +Signed-off-by: RISE Project CI +--- + extension/llm/custom_ops/CMakeLists.txt | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/extension/llm/custom_ops/CMakeLists.txt b/extension/llm/custom_ops/CMakeLists.txt +index fa847cb..d9f6e4f 100644 +--- a/extension/llm/custom_ops/CMakeLists.txt ++++ b/extension/llm/custom_ops/CMakeLists.txt +@@ -58,10 +58,16 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)") + "extension/llm/custom_ops/spinquant/third-party/FFHT/fht_avx.c" + ) + else() ++ # No FFHT SIMD kernel exists for this architecture, but none is required: ++ # fast_hadamard_transform_ffht_impl() (fast_hadamard_transform.h) only ++ # calls fht_float() when __aarch64__ or __x86_64__ is defined, and already ++ # falls back at compile time to the portable ++ # fast_hadamard_transform_simple_impl() everywhere else, so nothing here ++ # links against fht_float/fht_double. + message( +- FATAL_ERROR +- "Unsupported CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}. (If \ +-32-bit x86, try using fht_avx.c and send a PR if it works!)" ++ STATUS ++ "No FFHT SIMD kernel for CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}; " ++ "using the portable fast_hadamard_transform_simple_impl fallback." + ) + endif() + +-- +2.34.1 diff --git a/patches/executorch/1.5.0/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch b/patches/executorch/1.5.0/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch new file mode 100644 index 000000000000..8632bcb6d9ac --- /dev/null +++ b/patches/executorch/1.5.0/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000006 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 9 Oct 2026 00:00:00 +0000 +Subject: [PATCH 6/7] xnnpack: only query cpuinfo uarchs once cpuinfo is + initialized + +init_hardware_config() checks cpuinfo_initialize() before reading the L1/L2 +data cache sizes, but the loop that fills hardware_config.uarch[] right +after it sits outside that check and calls cpuinfo_get_uarch() +unconditionally. When cpuinfo cannot initialize, cpuinfo_get_uarch() is +fatal: + + Fatal error in cpuinfo: cpuinfo_get_uarch called before cpuinfo is initialized + +and the process aborts. XnnpackBackend's static registration calls +xnn_initialize() while _portable_lib is being loaded, so this kills +`import executorch.extension.pybindings.portable_lib` outright. + +xnn_init_hardware_config() deliberately skips its cpuinfo_initialize() +gate on XNN_ARCH_RISCV and XNN_ARCH_PPC64 (both detect their vector +extensions through getauxval() instead), so on those architectures +init_hardware_config() is reached with cpuinfo uninitialized whenever +cpuinfo cannot parse the host's topology - e.g. a riscv64 kernel that +reports /sys/devices/system/cpu/cpuN/topology/core_id as -1. Only query +the uarchs when cpuinfo_initialize() succeeds and otherwise record +xnn_uarch_unknown, which is what the !XNN_ENABLE_CPUINFO branch already +does. + +Upstream-Status: To upstream [not yet submitted to google/XNNPACK; unchanged on XNNPACK master, affects every architecture whose xnn_init_hardware_config() skips the cpuinfo_initialize() gate (riscv64, ppc64) on hosts where cpuinfo cannot initialize] + +Signed-off-by: RISE Project CI +--- + .../XNNPACK/src/configs/hardware-config.c | 22 ++++++++++++------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c b/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c +index da518a1..620c202 100644 +--- a/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c ++++ b/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c +@@ -448,16 +448,22 @@ static void init_hardware_config(void) { + } + } + ++ if (cpuinfo_initialize()) { + #if XNN_MAX_UARCH_TYPES > 1 +- // Print what we think we know about the microarchs. +- xnn_log_info("cpuinfo_get_uarchs_count: %u.", cpuinfo_get_uarchs_count()); +- for (int i = 0; i < cpuinfo_get_uarchs_count(); i++) { +- xnn_log_info("cpu_get_uarch(%i): 0x%x", i, cpuinfo_get_uarch(i)->uarch); +- } ++ // Print what we think we know about the microarchs. ++ xnn_log_info("cpuinfo_get_uarchs_count: %u.", cpuinfo_get_uarchs_count()); ++ for (int i = 0; i < cpuinfo_get_uarchs_count(); i++) { ++ xnn_log_info("cpu_get_uarch(%i): 0x%x", i, cpuinfo_get_uarch(i)->uarch); ++ } + #endif // XNN_MAX_UARCH_TYPES > 1 +- for (size_t i = 0; i < XNN_MAX_UARCH_TYPES; ++i) { +- const struct cpuinfo_uarch_info* uarch = cpuinfo_get_uarch(i); +- hardware_config.uarch[i] = uarch ? cpuinfo_to_xnn_uarch(uarch->uarch) : xnn_uarch_unknown; ++ for (size_t i = 0; i < XNN_MAX_UARCH_TYPES; ++i) { ++ const struct cpuinfo_uarch_info* uarch = cpuinfo_get_uarch(i); ++ hardware_config.uarch[i] = uarch ? cpuinfo_to_xnn_uarch(uarch->uarch) : xnn_uarch_unknown; ++ } ++ } else { ++ for (size_t i = 0; i < XNN_MAX_UARCH_TYPES; ++i) { ++ hardware_config.uarch[i] = xnn_uarch_unknown; ++ } + } + #else + xnn_log_warning("Unable to determine L1/L2 data cache properties."); +-- +2.43.0 + diff --git a/patches/executorch/1.5.0/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch b/patches/executorch/1.5.0/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch new file mode 100644 index 000000000000..d74a1e05fb51 --- /dev/null +++ b/patches/executorch/1.5.0/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000007 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 9 Oct 2026 00:00:00 +0000 +Subject: [PATCH 7/7] threadpool: fall back to the online CPU count when + cpuinfo fails + +get_threadpool() returns nullptr when cpuinfo_initialize() fails, but +none of its callers handle that: get_pthreadpool() aborts with "Failed to +acquire an instance of ThreadPool!" (reached from XNNCompiler.cpp when +creating every XNNPACK runtime), and parallel_for(), +_threadpool_get_thread_count() and the LLM sdpa op dereference the +result directly. So on any host where cpuinfo cannot initialize - e.g. a +riscv64 kernel that reports /sys/devices/system/cpu/cpuN/topology/core_id +as -1 - running an XNNPACK-delegated or parallelised program crashes. + +cpuinfo is only used here to choose a thread count: pthreadpool itself is +built with PTHREADPOOL_USE_CPUINFO=0 and starts its threads without it. +Size the pool from std::thread::hardware_concurrency() (capped at the +same tsan limit of 63) when cpuinfo is unavailable, instead of leaving +every caller without a threadpool. + +Upstream-Status: To upstream [not yet submitted; unchanged on pytorch/executorch main, affects any host where cpuinfo_initialize() fails, independent of riscv64] + +Signed-off-by: RISE Project CI +--- + extension/threadpool/threadpool.cpp | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/extension/threadpool/threadpool.cpp b/extension/threadpool/threadpool.cpp +index 2845b4a..a3a8c60 100644 +--- a/extension/threadpool/threadpool.cpp ++++ b/extension/threadpool/threadpool.cpp +@@ -11,6 +11,7 @@ + + #include + #include ++#include + + #include + #include +@@ -127,12 +128,14 @@ void ThreadPool::run( + ThreadPool* get_threadpool() { + executorch::runtime::runtime_init(); + +- if (!cpuinfo_initialize()) { +- ET_LOG(Error, "cpuinfo initialization failed"); +- return nullptr; // NOLINT(facebook-hte-NullableReturn) +- } +- + static const int num_threads = ([]() { ++ if (!cpuinfo_initialize()) { ++ // pthreadpool does not need cpuinfo, so size the pool from the online ++ // CPU count instead of leaving every caller without a threadpool. ++ ET_LOG(Info, "cpuinfo initialization failed, using the online CPU count"); ++ const uint32_t online = std::thread::hardware_concurrency(); ++ return std::min(std::max(online, 1u), 63u); ++ } + #if defined(EXECUTORCH_THREADPOOL_USE_ALL_LOGICAL_CORES) + // Use threads=cores. + auto result = cpuinfo_get_processors_count(); +-- +2.43.0 + From d29541a80b5d38f31771c137a883c36211b1ebca Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Fri, 23 Oct 2026 02:21:50 +0800 Subject: [PATCH 3/5] executorch: Carry patches over to version 1.5.1 Same set as 1.5.0 (rebased 0003 and 0004; the rest unchanged). --- ...de-vendored-third-party-licences-in-.patch | 34 ++++++ ...rce-directory-name-check-for-cibuild.patch | 65 ++++++++++ ...bind-extensions-as-MODULE-not-SHARED.patch | 115 ++++++++++++++++++ ...able_lib-SHARED-for-llm-runner-linka.patch | 79 ++++++++++++ ...-simd-arch-fatal-error-portable-fall.patch | 73 +++++++++++ ...ry-cpuinfo-uarchs-once-cpuinfo-is-in.patch | 73 +++++++++++ ...back-to-the-online-CPU-count-when-cp.patch | 63 ++++++++++ 7 files changed, 502 insertions(+) create mode 100644 patches/executorch/1.5.1/0001-packaging-Include-vendored-third-party-licences-in-.patch create mode 100644 patches/executorch/1.5.1/0002-cmake-relax-source-directory-name-check-for-cibuild.patch create mode 100644 patches/executorch/1.5.1/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch create mode 100644 patches/executorch/1.5.1/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch create mode 100644 patches/executorch/1.5.1/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch create mode 100644 patches/executorch/1.5.1/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch create mode 100644 patches/executorch/1.5.1/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch diff --git a/patches/executorch/1.5.1/0001-packaging-Include-vendored-third-party-licences-in-.patch b/patches/executorch/1.5.1/0001-packaging-Include-vendored-third-party-licences-in-.patch new file mode 100644 index 000000000000..7e65c08e10ed --- /dev/null +++ b/patches/executorch/1.5.1/0001-packaging-Include-vendored-third-party-licences-in-.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000001 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Thu, 10 Jul 2026 00:00:00 +0000 +Subject: [PATCH] packaging: Include vendored third-party licences in the + wheel + +The compiled extensions in this wheel statically link FP16, FXdiv, +XNNPACK, cpuinfo, pthreadpool, flatbuffers, flatcc, Eigen, pocketfft, +nlohmann/json and pybind11, but `license-files` only reaches the +project's own LICENSE. RISE distributes these wheels and must also +carry the licence of every statically linked dependency, so widen the +glob to pick up the `LICENSE.` files the riscv64 build stages at +the project root before `pip wheel` runs. + +Upstream-Status: Inappropriate [only relevant to a distributor bundling vendored third-party licences; reproduces identically on any architecture] + +Signed-off-by: RISE Project CI +--- + pyproject.toml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pyproject.toml b/pyproject.toml +index 0000000000..0000000000 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -100,7 +100,7 @@ + # package, and package_data to restrict the set up non-python files we + # include. See also setuptools/discovery.py for custom finders. + [tool.setuptools] +-license-files = ["LICENSE"] ++license-files = ["LICENSE", "LICENSE.*"] + + [tool.setuptools.package-dir] + # Tell setuptools to follow the symlink: src/executorch/* -> * for all first level diff --git a/patches/executorch/1.5.1/0002-cmake-relax-source-directory-name-check-for-cibuild.patch b/patches/executorch/1.5.1/0002-cmake-relax-source-directory-name-check-for-cibuild.patch new file mode 100644 index 000000000000..41e36734ac70 --- /dev/null +++ b/patches/executorch/1.5.1/0002-cmake-relax-source-directory-name-check-for-cibuild.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000002 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Thu, 10 Jul 2026 00:00:00 +0000 +Subject: [PATCH] cmake: stop requiring the checkout dir be named `executorch` + +CMakeLists.txt hard-fails configure unless the checkout's directory is +named exactly `executorch`, because `_common_include_directories` adds +the checkout's *parent* directory so in-tree code can say +`#include ` (upstream tracks lifting this +restriction at https://github.com/pytorch/executorch/issues/6475). + +cibuildwheel always mounts/copies the source into its manylinux +container at the fixed path `/project`, so this check always trips +there, regardless of what directory this repo is checked out to on the +runner. Provide the same `` include path through a +configure-time symlink instead of requiring a literally named parent +directory, so the build works unmodified under cibuildwheel. + +Upstream-Status: Inappropriate [only relevant to cibuildwheel, which always mounts the source at a fixed /project path inside its build container; see pytorch/executorch#6475] + +Signed-off-by: RISE Project CI +--- + CMakeLists.txt | 20 +++++++++----------- + 1 file changed, 9 insertions(+), 11 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index be0cec2..4668d0a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -447,22 +447,20 @@ if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE + list(APPEND _common_compile_options $<$>:-fPIC>) + endif() + +-# Let files say "include ". +-# TODO(#6475): This requires/assumes that the repo lives in a directory named +-# exactly `executorch`. Check the assumption first. Remove this check once we +-# stop relying on the assumption. +-cmake_path(GET CMAKE_CURRENT_SOURCE_DIR FILENAME _repo_dir_name) +-if(NOT "${_repo_dir_name}" STREQUAL "executorch") +- message( +- FATAL_ERROR +- "The ExecuTorch repo must be cloned into a directory named exactly " +- "`executorch`; found `${_repo_dir_name}`. See " +- "https://github.com/pytorch/executorch/issues/6475 for progress on a " +- "fix for this restriction." ++# Let files say "include ", regardless of what ++# the checkout directory is actually named (see ++# https://github.com/pytorch/executorch/issues/6475). Provide that include ++# path unconditionally through a configure-time symlink, rather than ++# requiring the checkout itself be named `executorch`. ++set(_executorch_include_shim "${CMAKE_BINARY_DIR}/_executorch_include") ++file(MAKE_DIRECTORY "${_executorch_include_shim}") ++if(NOT EXISTS "${_executorch_include_shim}/executorch") ++ file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}" ++ "${_executorch_include_shim}/executorch" SYMBOLIC + ) + endif() + set(_common_include_directories +- $ ++ $ + $ + $ + $ +-- +2.34.1 diff --git a/patches/executorch/1.5.1/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch b/patches/executorch/1.5.1/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch new file mode 100644 index 000000000000..6819d082c2df --- /dev/null +++ b/patches/executorch/1.5.1/0003-cmake-build-pybind-extensions-as-MODULE-not-SHARED.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000003 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Mon, 28 Sep 2026 00:00:00 +0000 +Subject: [PATCH] cmake: build pybind extensions as MODULE, not SHARED + +pybind11_add_module( SHARED ...) makes CMake's Python_add_library() +require the Python::Python target (COMPONENT Development.Embed) to exist +at configure time, even though strip_python_lib() immediately removes the +resulting Python::Python/pybind11::embed link dependency again -- these +are ordinary dlopen()'d extension modules that resolve Python symbols +from the running interpreter, never anything that embeds Python. + +Vanilla manylinux images (unlike the custom manylinux-builder images +PyTorch's own CI uses) ship only a static libpythonX.Y.a and never +satisfy Development.Embed, so find_package(Python) never defines +Python::Python and every pybind11_add_module(... SHARED ...) call fails +configure outright: + + CMake Error: Python_ADD_LIBRARY: dependent target 'Python::Python' is + not defined. Did you miss to request COMPONENT 'Development.Embed'? + +Dropping SHARED (the pybind11 default, MODULE) only requires +Development.Module, which these images do provide, and produces the +exact same importable extension: strip_python_lib()'s job of avoiding a +runtime libpython link was already redundant with MODULE all along. + +Upstream-Status: To upstream [not yet submitted; a real portability bug on any vanilla manylinux image lacking an embeddable libpython (Development.Embed), independent of riscv64 -- pytorch/executorch's own CI runs a custom manylinux-builder image that does provide one, so upstream has likely never hit this] + +Signed-off-by: RISE Project CI +--- + CMakeLists.txt | 4 ++-- + backends/apple/coreml/CMakeLists.txt | 2 +- + codegen/tools/CMakeLists.txt | 2 +- + extension/llm/runner/CMakeLists.txt | 2 +- + extension/training/CMakeLists.txt | 2 +- + 5 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 93e02c5..ac73707 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1397,7 +1397,7 @@ if(EXECUTORCH_BUILD_PYBIND) + endif() + + # pybind portable_lib +- pybind11_add_module(portable_lib SHARED extension/pybindings/pybindings.cpp) ++ pybind11_add_module(portable_lib extension/pybindings/pybindings.cpp) + strip_python_lib(portable_lib) + # The actual output file needs a leading underscore so it can coexist with + # portable_lib.py in the same python package. PyTorch requires C++20, so +@@ -1488,7 +1488,7 @@ if(EXECUTORCH_BUILD_PYBIND) + # pybind data_loader module - provides PyDataLoader type for external + # pybinding extensions to create custom data loaders + pybind11_add_module( +- data_loader SHARED extension/pybindings/pybindings_data_loader.cpp ++ data_loader extension/pybindings/pybindings_data_loader.cpp + ) + strip_python_lib(data_loader) + target_include_directories(data_loader PRIVATE ${_common_include_directories}) +diff --git a/backends/apple/coreml/CMakeLists.txt b/backends/apple/coreml/CMakeLists.txt +index 8df0cfd..fb07e6e 100644 +--- a/backends/apple/coreml/CMakeLists.txt ++++ b/backends/apple/coreml/CMakeLists.txt +@@ -181,7 +181,7 @@ install( + + if(EXECUTORCH_BUILD_PYBIND) + pybind11_add_module( +- executorchcoreml SHARED runtime/inmemoryfs/inmemory_filesystem_py.cpp ++ executorchcoreml runtime/inmemoryfs/inmemory_filesystem_py.cpp + runtime/inmemoryfs/inmemory_filesystem_utils.cpp + ) + strip_python_lib(executorchcoreml) +diff --git a/codegen/tools/CMakeLists.txt b/codegen/tools/CMakeLists.txt +index 143d2c1..d95716d 100644 +--- a/codegen/tools/CMakeLists.txt ++++ b/codegen/tools/CMakeLists.txt +@@ -8,7 +8,7 @@ + # Check if pybind11 is available + + # Create the selective_build pybind11 module +-pybind11_add_module(selective_build SHARED selective_build.cpp) ++pybind11_add_module(selective_build selective_build.cpp) + strip_python_lib(selective_build) + + # Set the output name to match the module name +diff --git a/extension/llm/runner/CMakeLists.txt b/extension/llm/runner/CMakeLists.txt +index 17016b9..110e252 100644 +--- a/extension/llm/runner/CMakeLists.txt ++++ b/extension/llm/runner/CMakeLists.txt +@@ -113,7 +113,7 @@ endif() + if(EXECUTORCH_BUILD_PYBIND) + # Create the Python extension module for LLM runners + pybind11_add_module( +- _llm_runner SHARED ${CMAKE_CURRENT_SOURCE_DIR}/pybindings.cpp ++ _llm_runner ${CMAKE_CURRENT_SOURCE_DIR}/pybindings.cpp + ) + strip_python_lib(_llm_runner) + +diff --git a/extension/training/CMakeLists.txt b/extension/training/CMakeLists.txt +index 7b76723..cabf478 100644 +--- a/extension/training/CMakeLists.txt ++++ b/extension/training/CMakeLists.txt +@@ -77,7 +77,7 @@ if(EXECUTORCH_BUILD_PYBIND) + endif() + + pybind11_add_module( +- _training_lib SHARED ++ _training_lib + ${CMAKE_CURRENT_SOURCE_DIR}/pybindings/_training_lib.cpp + ) + strip_python_lib(_training_lib) + +-- +2.34.1 + diff --git a/patches/executorch/1.5.1/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch b/patches/executorch/1.5.1/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch new file mode 100644 index 000000000000..370015c5cd67 --- /dev/null +++ b/patches/executorch/1.5.1/0004-cmake-keep-portable_lib-SHARED-for-llm-runner-linka.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000004 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Mon, 28 Sep 2026 00:00:00 +0000 +Subject: [PATCH] cmake: keep portable_lib SHARED for llm/runner linkage + +0003 converted all six pybind11_add_module( SHARED ...) call sites to +plain pybind11_add_module( ...) (MODULE), since vanilla manylinux +images never satisfy Python_add_library(SHARED)'s Python::Python +(Development.Embed) requirement. portable_lib is not like the other five, +though: extension/llm/runner/CMakeLists.txt does +target_link_libraries(_llm_runner PRIVATE ... portable_lib ...), and CMake +refuses to link a MODULE_LIBRARY into another target at all: + + CMake Error: Target "portable_lib" of type MODULE_LIBRARY may not be + linked into another target. One may link only to INTERFACE, OBJECT, + STATIC or SHARED libraries, or to executables with the ENABLE_EXPORTS + property set. + +This is a CMake generator restriction on the target type itself (checked in +every CMake version's link-dependency analysis), not something any +pybind11_add_module() argument can opt out of -- so portable_lib has to stay +SHARED, and the Development.Embed gap has to be closed some other way. + +FindPython's __Python_ADD_LIBRARY() (Modules/FindPython/Support.cmake) +requires the Python::Python target to already exist before it will even +add_library(... SHARED ...), and then links the new target against it: + + if (NOT type STREQUAL "MODULE" AND NOT TARGET ${prefix}::Python) + message (SEND_ERROR "...dependent target '${prefix}::Python' is not + defined. Did you miss to request COMPONENT 'Development.Embed'?") + ... + target_link_libraries (${name} PRIVATE ${prefix}::Python) + +Nothing requires that target to carry a real embeddable libpython, though: +defining Python::Python ourselves as a link-free INTERFACE IMPORTED target +when Development.Embed didn't find one satisfies the existence check, and +strip_python_lib() (already applied to portable_lib right below) then +removes Python::Python/pybind11::embed from portable_lib's real link line +exactly as it already does for the other five, now-MODULE targets -- so no +embeddable libpython is ever actually linked, and portable_lib comes out +identical to what it built as on upstream's own manylinux-builder CI, which +does have Development.Embed and never exercises this fallback. + +Upstream-Status: To upstream [not yet submitted; a real portability bug on any vanilla manylinux image lacking an embeddable libpython (Development.Embed), independent of riscv64, same as 0003] + +Signed-off-by: RISE Project CI +--- + CMakeLists.txt | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ac73707..c2bcca2 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1397,7 +1397,20 @@ if(EXECUTORCH_BUILD_PYBIND) + endif() + + # pybind portable_lib +- pybind11_add_module(portable_lib extension/pybindings/pybindings.cpp) ++ # Unlike the other five pybind11_add_module() call sites, portable_lib is ++ # itself target_link_libraries()'d into extension/llm/runner's _llm_runner, ++ # and CMake refuses to link a MODULE_LIBRARY into another target -- so this ++ # one has to stay SHARED. Python_add_library(SHARED) unconditionally ++ # requires a Python::Python target to already exist (Development.Embed), ++ # which vanilla manylinux images never provide; define it as a link-free ++ # stand-in when missing so the SHARED add_library() call is allowed to ++ # proceed. strip_python_lib() below removes it (and pybind11::embed) from ++ # portable_lib's real link line either way, so no embeddable libpython is ++ # ever actually required. ++ if(NOT TARGET Python::Python) ++ add_library(Python::Python INTERFACE IMPORTED) ++ endif() ++ pybind11_add_module(portable_lib SHARED extension/pybindings/pybindings.cpp) + strip_python_lib(portable_lib) + # The actual output file needs a leading underscore so it can coexist with + # portable_lib.py in the same python package. PyTorch requires C++20, so + +-- +2.34.1 diff --git a/patches/executorch/1.5.1/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch b/patches/executorch/1.5.1/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch new file mode 100644 index 000000000000..5ec70df461bd --- /dev/null +++ b/patches/executorch/1.5.1/0005-cmake-drop-FFHT-simd-arch-fatal-error-portable-fall.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000005 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Mon, 28 Sep 2026 00:00:00 +0000 +Subject: [PATCH] cmake: drop FFHT SIMD arch fatal error, portable fallback exists + +extension/llm/custom_ops/CMakeLists.txt picks a vendored FFHT (Fast +Hadamard Transform) SIMD kernel source file to compile based on +CMAKE_SYSTEM_PROCESSOR -- fht_neon.c for aarch64/arm64/armv7, fht_avx.c for +x86_64/AMD64 -- and hard-errors for every other architecture, riscv64 +included: + + CMake Error: Unsupported CMAKE_SYSTEM_PROCESSOR riscv64. (If 32-bit x86, + try using fht_avx.c and send a PR if it works!) + +But nothing on such an architecture actually needs an FFHT SIMD kernel. +extension/llm/custom_ops/spinquant/fast_hadamard_transform.h's +fast_hadamard_transform_ffht_impl() -- the only caller of fht_float()/ +fht_double() outside the vendored FFHT sources themselves -- already +branches on the compiler-defined architecture macros, not +CMAKE_SYSTEM_PROCESSOR: + + #if defined(__aarch64__) || defined(__x86_64__) + fht_float(vec, log2_vec_size); + normalize_after_fht(vec, log2_vec_size); + #else + fast_hadamard_transform_simple_impl(vec, log2_vec_size); + #endif + +so on any architecture other than __aarch64__/__x86_64__ -- riscv64 +included -- the portable, scalar fast_hadamard_transform_simple_impl() is +already used at compile time, and the FFHT SIMD kernel's fht_float()/ +fht_double() symbols are never referenced, let alone linked. The +CMakeLists.txt FATAL_ERROR was refusing to configure over a source file +that would never have been needed. Replace it with a STATUS message and +add no FFHT source at all for these architectures; the vendored fht_avx.c/ +fht_neon.c/fht_sse.c/dumb_fht.c files use a different, narrower API +(void dumb_fht(float*, int) vs. fht_float()'s int fht_float(float*, int), +and no fht_double()/_oop equivalents) and were never a drop-in match +regardless of architecture. + +Upstream-Status: To upstream [not yet submitted; the FATAL_ERROR blocks every architecture outside x86_64/aarch64/armv7 even though fast_hadamard_transform.h already has a portable fallback that needs none of them, independent of riscv64] + +Signed-off-by: RISE Project CI +--- + extension/llm/custom_ops/CMakeLists.txt | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/extension/llm/custom_ops/CMakeLists.txt b/extension/llm/custom_ops/CMakeLists.txt +index fa847cb..d9f6e4f 100644 +--- a/extension/llm/custom_ops/CMakeLists.txt ++++ b/extension/llm/custom_ops/CMakeLists.txt +@@ -58,10 +58,16 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)") + "extension/llm/custom_ops/spinquant/third-party/FFHT/fht_avx.c" + ) + else() ++ # No FFHT SIMD kernel exists for this architecture, but none is required: ++ # fast_hadamard_transform_ffht_impl() (fast_hadamard_transform.h) only ++ # calls fht_float() when __aarch64__ or __x86_64__ is defined, and already ++ # falls back at compile time to the portable ++ # fast_hadamard_transform_simple_impl() everywhere else, so nothing here ++ # links against fht_float/fht_double. + message( +- FATAL_ERROR +- "Unsupported CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}. (If \ +-32-bit x86, try using fht_avx.c and send a PR if it works!)" ++ STATUS ++ "No FFHT SIMD kernel for CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}; " ++ "using the portable fast_hadamard_transform_simple_impl fallback." + ) + endif() + +-- +2.34.1 diff --git a/patches/executorch/1.5.1/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch b/patches/executorch/1.5.1/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch new file mode 100644 index 000000000000..8632bcb6d9ac --- /dev/null +++ b/patches/executorch/1.5.1/0006-xnnpack-only-query-cpuinfo-uarchs-once-cpuinfo-is-in.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000006 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 9 Oct 2026 00:00:00 +0000 +Subject: [PATCH 6/7] xnnpack: only query cpuinfo uarchs once cpuinfo is + initialized + +init_hardware_config() checks cpuinfo_initialize() before reading the L1/L2 +data cache sizes, but the loop that fills hardware_config.uarch[] right +after it sits outside that check and calls cpuinfo_get_uarch() +unconditionally. When cpuinfo cannot initialize, cpuinfo_get_uarch() is +fatal: + + Fatal error in cpuinfo: cpuinfo_get_uarch called before cpuinfo is initialized + +and the process aborts. XnnpackBackend's static registration calls +xnn_initialize() while _portable_lib is being loaded, so this kills +`import executorch.extension.pybindings.portable_lib` outright. + +xnn_init_hardware_config() deliberately skips its cpuinfo_initialize() +gate on XNN_ARCH_RISCV and XNN_ARCH_PPC64 (both detect their vector +extensions through getauxval() instead), so on those architectures +init_hardware_config() is reached with cpuinfo uninitialized whenever +cpuinfo cannot parse the host's topology - e.g. a riscv64 kernel that +reports /sys/devices/system/cpu/cpuN/topology/core_id as -1. Only query +the uarchs when cpuinfo_initialize() succeeds and otherwise record +xnn_uarch_unknown, which is what the !XNN_ENABLE_CPUINFO branch already +does. + +Upstream-Status: To upstream [not yet submitted to google/XNNPACK; unchanged on XNNPACK master, affects every architecture whose xnn_init_hardware_config() skips the cpuinfo_initialize() gate (riscv64, ppc64) on hosts where cpuinfo cannot initialize] + +Signed-off-by: RISE Project CI +--- + .../XNNPACK/src/configs/hardware-config.c | 22 ++++++++++++------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c b/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c +index da518a1..620c202 100644 +--- a/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c ++++ b/backends/xnnpack/third-party/XNNPACK/src/configs/hardware-config.c +@@ -448,16 +448,22 @@ static void init_hardware_config(void) { + } + } + ++ if (cpuinfo_initialize()) { + #if XNN_MAX_UARCH_TYPES > 1 +- // Print what we think we know about the microarchs. +- xnn_log_info("cpuinfo_get_uarchs_count: %u.", cpuinfo_get_uarchs_count()); +- for (int i = 0; i < cpuinfo_get_uarchs_count(); i++) { +- xnn_log_info("cpu_get_uarch(%i): 0x%x", i, cpuinfo_get_uarch(i)->uarch); +- } ++ // Print what we think we know about the microarchs. ++ xnn_log_info("cpuinfo_get_uarchs_count: %u.", cpuinfo_get_uarchs_count()); ++ for (int i = 0; i < cpuinfo_get_uarchs_count(); i++) { ++ xnn_log_info("cpu_get_uarch(%i): 0x%x", i, cpuinfo_get_uarch(i)->uarch); ++ } + #endif // XNN_MAX_UARCH_TYPES > 1 +- for (size_t i = 0; i < XNN_MAX_UARCH_TYPES; ++i) { +- const struct cpuinfo_uarch_info* uarch = cpuinfo_get_uarch(i); +- hardware_config.uarch[i] = uarch ? cpuinfo_to_xnn_uarch(uarch->uarch) : xnn_uarch_unknown; ++ for (size_t i = 0; i < XNN_MAX_UARCH_TYPES; ++i) { ++ const struct cpuinfo_uarch_info* uarch = cpuinfo_get_uarch(i); ++ hardware_config.uarch[i] = uarch ? cpuinfo_to_xnn_uarch(uarch->uarch) : xnn_uarch_unknown; ++ } ++ } else { ++ for (size_t i = 0; i < XNN_MAX_UARCH_TYPES; ++i) { ++ hardware_config.uarch[i] = xnn_uarch_unknown; ++ } + } + #else + xnn_log_warning("Unable to determine L1/L2 data cache properties."); +-- +2.43.0 + diff --git a/patches/executorch/1.5.1/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch b/patches/executorch/1.5.1/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch new file mode 100644 index 000000000000..d74a1e05fb51 --- /dev/null +++ b/patches/executorch/1.5.1/0007-threadpool-fall-back-to-the-online-CPU-count-when-cp.patch @@ -0,0 +1,63 @@ +From 0000000000000000000000000000000000000007 Mon Sep 17 00:00:00 2001 +From: RISE Project CI +Date: Fri, 9 Oct 2026 00:00:00 +0000 +Subject: [PATCH 7/7] threadpool: fall back to the online CPU count when + cpuinfo fails + +get_threadpool() returns nullptr when cpuinfo_initialize() fails, but +none of its callers handle that: get_pthreadpool() aborts with "Failed to +acquire an instance of ThreadPool!" (reached from XNNCompiler.cpp when +creating every XNNPACK runtime), and parallel_for(), +_threadpool_get_thread_count() and the LLM sdpa op dereference the +result directly. So on any host where cpuinfo cannot initialize - e.g. a +riscv64 kernel that reports /sys/devices/system/cpu/cpuN/topology/core_id +as -1 - running an XNNPACK-delegated or parallelised program crashes. + +cpuinfo is only used here to choose a thread count: pthreadpool itself is +built with PTHREADPOOL_USE_CPUINFO=0 and starts its threads without it. +Size the pool from std::thread::hardware_concurrency() (capped at the +same tsan limit of 63) when cpuinfo is unavailable, instead of leaving +every caller without a threadpool. + +Upstream-Status: To upstream [not yet submitted; unchanged on pytorch/executorch main, affects any host where cpuinfo_initialize() fails, independent of riscv64] + +Signed-off-by: RISE Project CI +--- + extension/threadpool/threadpool.cpp | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/extension/threadpool/threadpool.cpp b/extension/threadpool/threadpool.cpp +index 2845b4a..a3a8c60 100644 +--- a/extension/threadpool/threadpool.cpp ++++ b/extension/threadpool/threadpool.cpp +@@ -11,6 +11,7 @@ + + #include + #include ++#include + + #include + #include +@@ -127,12 +128,14 @@ void ThreadPool::run( + ThreadPool* get_threadpool() { + executorch::runtime::runtime_init(); + +- if (!cpuinfo_initialize()) { +- ET_LOG(Error, "cpuinfo initialization failed"); +- return nullptr; // NOLINT(facebook-hte-NullableReturn) +- } +- + static const int num_threads = ([]() { ++ if (!cpuinfo_initialize()) { ++ // pthreadpool does not need cpuinfo, so size the pool from the online ++ // CPU count instead of leaving every caller without a threadpool. ++ ET_LOG(Info, "cpuinfo initialization failed, using the online CPU count"); ++ const uint32_t online = std::thread::hardware_concurrency(); ++ return std::min(std::max(online, 1u), 63u); ++ } + #if defined(EXECUTORCH_THREADPOOL_USE_ALL_LOGICAL_CORES) + // Use threads=cores. + auto result = cpuinfo_get_processors_count(); +-- +2.43.0 + From b5a6b933d3bcdc2039dc0682dbe3071c6a4ed65c Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sat, 24 Oct 2026 11:58:16 +0800 Subject: [PATCH 4/5] executorch: Disable XNNPACK's RISC-V fp16 vector kernels (binutils 2.41 lacks zvfh) --- .github/workflows/build-executorch.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-executorch.yml b/.github/workflows/build-executorch.yml index 2741ac794046..b880ff4a377a 100644 --- a/.github/workflows/build-executorch.yml +++ b/.github/workflows/build-executorch.yml @@ -185,9 +185,14 @@ jobs: pip install --only-binary=:all: "torch==2.13.0" # Without BUILD_VERSION, setup.py appends + to version.txt # (mirrors build-torchaudio.yml / build-torchcodec.yml). + # XNNPACK's rvvfp16arith microkernels are assembled with -march=..._zvfh, which + # the image's binutils 2.41 rejects (zvfh landed in 2.42; gotcha 420), so the + # fp16 vector family is switched off; plain RVV stays enabled. The XNNPACK + # pinned by 1.5.x has these kernels, 1.4.1's does not and ignores the option. CIBW_ENVIRONMENT: >- BUILD_VERSION=${{ env.EXECUTORCH_VERSION }} CMAKE_BUILD_PARALLEL_LEVEL=8 + CMAKE_ARGS="-DXNNPACK_ENABLE_RISCV_FP16_VECTOR=OFF" PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ # The torch wheel already carries these and loads them RTLD_GLOBAL (gotcha 17). CIBW_REPAIR_WHEEL_COMMAND: >- From f364d8bddfb95a0fc9a8278f4d3ff7d693a36757 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Sun, 25 Oct 2026 19:02:30 +0100 Subject: [PATCH 5/5] executorch: install pandas wheel-only in the test stage --- .github/workflows/build-executorch.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build-executorch.yml b/.github/workflows/build-executorch.yml index b880ff4a377a..aafc032c9430 100644 --- a/.github/workflows/build-executorch.yml +++ b/.github/workflows/build-executorch.yml @@ -205,6 +205,13 @@ jobs: --exclude libgomp.so.1 --exclude libgfortran.so.5 --exclude libopenblas.so.0 + # The test install of the executorch wheel pulls pandas as a dependency; + # PyPI's newest pandas has no riscv64 wheel and its sdist fails to build + # (meson/xsimd), so install pandas wheel-only, with the registry's + # riscv64 wheels visible, and let pip back off to a release that has one. + CIBW_TEST_ENVIRONMENT: >- + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + PIP_ONLY_BINARY=pandas # Match the build-time pin (gotcha 615): the wheel's own metadata still # says "torch>=2.13.0a0", so without this the test install would resolve # a newer torch than the extension was actually compiled against.