Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .ci/scripts/test_backend.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ if [[ "$FLOW" == *qnn* ]]; then
EXTRA_BUILD_ARGS+=" -DEXECUTORCH_BUILD_QNN=ON -DQNN_SDK_ROOT=$QNN_SDK_ROOT -DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON"
fi

if [[ "$FLOW" == *cpu* ]]; then
EXTRA_BUILD_ARGS+=" -DEXECUTORCH_BUILD_CPU=ON -DEXECUTORCH_BUILD_XNNPACK=ON -DEXECUTORCH_BUILD_KERNELS_OPTIMIZED=ON"
fi

if [[ "$FLOW" == *vulkan* ]]; then
# CPU runners can have Mesa ICDs installed without a usable hardware GPU.
source .ci/scripts/setup-vulkan-linux-deps.sh "swiftshader"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/_test_backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_call:
inputs:
backend:
description: 'Backend to test (xnnpack, coreml, vulkan, qnn, openvino)'
description: 'Backend to test (xnnpack, coreml, vulkan, qnn, openvino, cpu)'
required: true
type: string
flows:
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/test-backend-cpu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Test CPU Backend

on:
schedule:
- cron: 0 2 * * *
push:
branches:
- main
- release/*
tags:
- ciflow/nightly/*
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }}-${{ github.ref_type == 'branch' && github.sha }}-${{ github.event_name == 'workflow_dispatch' }}-${{ github.event_name == 'schedule' }}
cancel-in-progress: true

jobs:
test-cpu:
uses: ./.github/workflows/_test_backend.yml
permissions:
id-token: write
contents: read
with:
backend: cpu
flows: '["cpu_fp32"]'
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
timeout: 120
run-linux: true
docker-image: ci-image:executorch-ubuntu-22.04-gcc11
18 changes: 15 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ endif()
if(EXECUTORCH_BUILD_NATIVE)
string(APPEND _executorch_backend_dependencies
"find_dependency(libzip CONFIG)\n"
"find_dependency(nlohmann_json CONFIG)\n" "find_dependency(Threads)\n"
"find_dependency(nlohmann_json CONFIG)\n"
)
endif()
if(EXECUTORCH_BUILD_NATIVE_GGML)
Expand All @@ -797,7 +797,10 @@ if(EXECUTORCH_BUILD_NATIVE_GGML)
" add_library(executorch_ggml ALIAS ggml::ggml)\n" "endif()\n"
)
endif()
if(EXECUTORCH_BUILD_VULKAN)
if(EXECUTORCH_BUILD_NATIVE
OR EXECUTORCH_BUILD_CPU
OR EXECUTORCH_BUILD_VULKAN
)
string(APPEND _executorch_backend_dependencies "find_dependency(Threads)\n")
endif()
configure_file(
Expand Down Expand Up @@ -1417,6 +1420,10 @@ if(EXECUTORCH_BUILD_PYBIND)
endif()
endif()

if(EXECUTORCH_BUILD_CPU)
list(APPEND _dep_libs cpu_backend)
endif()

if(EXECUTORCH_BUILD_VULKAN)
list(APPEND _dep_libs vulkan_backend)
endif()
Expand Down Expand Up @@ -1624,10 +1631,15 @@ if(EXECUTORCH_BUILD_VULKAN)
list(APPEND _executorch_backends vulkan_backend vulkan_schema)
endif()

if(EXECUTORCH_BUILD_NATIVE)
if(EXECUTORCH_BUILD_NATIVE OR EXECUTORCH_BUILD_CPU)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/backends/native)
endif()

if(EXECUTORCH_BUILD_CPU)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/backends/cpu)
list(APPEND _executorch_backends cpu_backend)
endif()

if(EXECUTORCH_BUILD_WEBGPU)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/backends/webgpu)
list(APPEND _executorch_backends webgpu_backend)
Expand Down
163 changes: 127 additions & 36 deletions backends/cpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,56 +4,147 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

add_library(
cpu_runtime runtime/KernelProvider.cpp runtime/CPUPlan.cpp
runtime/op_helpers/Convolution.cpp
)
target_link_libraries(
cpu_runtime
PUBLIC native_runtime
PRIVATE extension_threadpool
cmake_minimum_required(VERSION 3.24)

if(NOT EXECUTORCH_ROOT)
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
endif()

include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake)

if(EXECUTORCH_BUILD_NATIVE_CPU)
add_library(
cpu_runtime runtime/KernelProvider.cpp runtime/CPUPlan.cpp
runtime/op_helpers/Convolution.cpp
)
target_link_libraries(
cpu_runtime
PUBLIC native_runtime
PRIVATE extension_threadpool
)
if(EXECUTORCH_BUILD_SHARED)
target_link_libraries(cpu_runtime PUBLIC executorch_shared)
else()
target_link_libraries(cpu_runtime PUBLIC executorch_core)
endif()

add_library(cpu_reference runtime/providers/reference/ReferenceProvider.cpp)
target_link_libraries(cpu_reference PUBLIC cpu_runtime)

add_library(cpu_xnnpack runtime/providers/xnnpack/XNNPACKProvider.cpp)
target_link_libraries(
cpu_xnnpack
PUBLIC cpu_runtime
PRIVATE extension_threadpool
)
if(EXECUTORCH_BUILD_SHARED)
target_link_libraries(cpu_xnnpack PRIVATE xnnpack_shared)
else()
target_link_libraries(cpu_xnnpack PRIVATE XNNPACK)
endif()

foreach(target cpu_runtime cpu_reference cpu_xnnpack)
add_library(executorch::${target} ALIAS ${target})
target_compile_features(${target} PUBLIC cxx_std_20)
target_compile_options(
${target} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/EHsc>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-fexceptions>
)
endforeach()

install(
TARGETS cpu_runtime cpu_reference cpu_xnnpack
EXPORT ExecuTorchTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(
DIRECTORY runtime/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/executorch/backends/cpu/runtime
FILES_MATCHING
PATTERN "*.h"
PATTERN "test" EXCLUDE
)
endif()

if(NOT EXECUTORCH_BUILD_CPU)
return()
endif()

# The provider composition that cpu_backend() in targets.bzl generates for the
# default :cpu_backend target.
set(_cpu_provider_registry ${CMAKE_CURRENT_BINARY_DIR}/provider_registry.cpp)
file(
GENERATE
OUTPUT ${_cpu_provider_registry}
CONTENT
"#include <executorch/backends/cpu/runtime/KernelProvider.h>
#include <executorch/backends/cpu/runtime/providers/xnnpack/XNNPACKProvider.h>
#include <executorch/backends/cpu/runtime/providers/reference/ReferenceProvider.h>
namespace executorch::backends::cpu {
namespace {
RuntimeConfiguration runtime_configuration() {
static const ProviderFactory factories[] = {create_xnnpack_provider,create_reference_provider};
return {{factories, sizeof(factories) / sizeof(factories[0])}, {}, false};
}
const bool registered = (register_runtime_configuration(runtime_configuration), true);
}
}
"
)

list(TRANSFORM _cpu_backend__srcs PREPEND "${EXECUTORCH_ROOT}/")
if(EXECUTORCH_BUILD_SHARED)
target_link_libraries(cpu_runtime PUBLIC executorch_shared)
set(_cpu_backend_library_type SHARED)
else()
target_link_libraries(cpu_runtime PUBLIC executorch_core)
set(_cpu_backend_library_type STATIC)
endif()

add_library(cpu_reference runtime/providers/reference/ReferenceProvider.cpp)
target_link_libraries(cpu_reference PUBLIC cpu_runtime)

add_library(cpu_xnnpack runtime/providers/xnnpack/XNNPACKProvider.cpp)
add_library(
cpu_backend ${_cpu_backend_library_type} ${_cpu_backend__srcs}
${_cpu_provider_registry}
)
target_link_libraries(
cpu_xnnpack
PUBLIC cpu_runtime
PRIVATE extension_threadpool
cpu_backend PRIVATE native_program extension_threadpool
optimized_native_cpu_ops_lib
)
if(EXECUTORCH_BUILD_SHARED)
target_link_libraries(cpu_xnnpack PRIVATE xnnpack_shared)
set_target_properties(
cpu_backend PROPERTIES OUTPUT_NAME executorch_backend_cpu
)
executorch_target_soname_policy(cpu_backend)
executorch_target_link_shared_runtime(cpu_backend)
# The XNNPACK delegate library already bundles XNNPACK, so resolve against it
# rather than shipping a second copy.
target_link_libraries(
cpu_backend
PUBLIC executorch_shared
PRIVATE xnnpack_backend
)
target_include_directories(
cpu_backend
PRIVATE $<TARGET_PROPERTY:XNNPACK,INTERFACE_INCLUDE_DIRECTORIES>
)
executorch_target_shipped_runtime_path(cpu_backend)
else()
target_link_libraries(cpu_xnnpack PRIVATE XNNPACK)
target_link_libraries(
cpu_backend
PUBLIC executorch_core
PRIVATE XNNPACK xnnpack-microkernels-prod
)
endif()

foreach(target cpu_runtime cpu_reference cpu_xnnpack)
add_library(executorch::${target} ALIAS ${target})
target_compile_features(${target} PUBLIC cxx_std_20)
target_compile_options(
${target} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/EHsc>
target_compile_features(cpu_backend PRIVATE cxx_std_20)
target_compile_options(
cpu_backend PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/EHsc>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-fexceptions>
)
endforeach()
)
set_target_properties(cpu_backend PROPERTIES POSITION_INDEPENDENT_CODE ON)
executorch_target_link_options_shared_lib(cpu_backend)

install(
TARGETS cpu_runtime cpu_reference cpu_xnnpack
TARGETS cpu_backend
EXPORT ExecuTorchTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(
DIRECTORY runtime/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/executorch/backends/cpu/runtime
FILES_MATCHING
PATTERN "*.h"
PATTERN "test" EXCLUDE
)
7 changes: 7 additions & 0 deletions backends/cpu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ The shared `KernelProvider` contract, `CPUPlan`, and `CpuBackend` remain in
[`targets.bzl`](targets.bzl).

The Buck `cpu_backend` target links the baseline XNNPACK and Reference providers.
The CMake `cpu_backend` target (`-DEXECUTORCH_BUILD_CPU=ON`, which requires
`-DEXECUTORCH_BUILD_XNNPACK=ON` and `-DEXECUTORCH_BUILD_KERNELS_OPTIMIZED=ON`)
links the same composition, including the full optimized and portable kernel
library for the Reference provider. Selective kernel builds are not supported.
The CPU backend is disabled by default, including in Python wheels. Enable it
for an editable install with
`CMAKE_ARGS="-DEXECUTORCH_BUILD_CPU=ON" ./install_executorch.sh --editable`.
Applications compose providers with [`cpu_backend()`](cpu_backend.bzl).

`CPUPlan` retains selection, regions, storage requirements and prepared executables
Expand Down
7 changes: 2 additions & 5 deletions backends/cpu/targets.bzl
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
load("@fbsource//xplat/executorch/backends/xnnpack/third-party:third_party_libs.bzl", "third_party_dep")
load("@fbsource//xplat/executorch/build:build_variables.bzl", "CPU_RUNTIME_BUCK_SRCS")
load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "runtime")
load(":cpu_backend.bzl", "cpu_backend", "cpu_provider")

def define_common_targets():
runtime.cxx_library(
name = "cpu_runtime",
srcs = [
"runtime/KernelProvider.cpp",
"runtime/CPUPlan.cpp",
"runtime/op_helpers/Convolution.cpp",
],
srcs = CPU_RUNTIME_BUCK_SRCS,
exported_headers = [
"runtime/KernelProvider.h",
"runtime/CPUPlan.h",
Expand Down
13 changes: 9 additions & 4 deletions backends/native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
endif()

find_package(Threads REQUIRED)
find_package(libzip CONFIG REQUIRED)
if(NOT TARGET nlohmann_json::nlohmann_json)
find_package(nlohmann_json CONFIG REQUIRED)

# A CPU backend build without EXECUTORCH_BUILD_NATIVE only needs the graph and
# the program reader, which have no third-party dependencies.
if(EXECUTORCH_BUILD_NATIVE)
find_package(libzip CONFIG REQUIRED)
if(NOT TARGET nlohmann_json::nlohmann_json)
find_package(nlohmann_json CONFIG REQUIRED)
endif()
endif()

add_subdirectory(runtime)
Expand Down Expand Up @@ -45,6 +50,6 @@ if(EXECUTORCH_BUILD_NATIVE_VISION_RUNNER OR EXECUTORCH_BUILD_NATIVE_LLM_RUNNER)
add_subdirectory(examples)
endif()

if(EXECUTORCH_BUILD_TESTS)
if(EXECUTORCH_BUILD_NATIVE AND EXECUTORCH_BUILD_TESTS)
add_subdirectory(test)
endif()
Loading
Loading