• 文件 >
  • 在 Apple 平台上整合及執行 ExecuTorch
捷徑

在 Apple 平台上整合及執行 ExecuTorch

作者: Anthony Shoumikhin

適用於 iOS 和 macOS 的 ExecuTorch 執行階段以預先構建的 .xcframework 二進位目標集合形式發布。 這些目標與 iOS 和 macOS 裝置及模擬器相容,並且提供發布和偵錯模式

  • executorch - 主要執行階段組件

  • backend_coreml - Core ML 後端

  • backend_mps - MPS 後端

  • backend_xnnpack - XNNPACK 後端

  • kernels_custom - LLM 的自訂核心

  • kernels_optimized - 最佳化核心

  • kernels_portable - 可移植核心(用作參考的簡單實作)

  • kernels_quantized - 量化核心

將您的二進位檔連結到 ExecuTorch 執行階段,以及匯出的 ML 模型使用的任何後端或核心。建議將核心執行階段連結到直接使用 ExecuTorch 的元件,並將核心和後端連結到主要的應用程式目標。

注意: 若要存取日誌,請連結到 ExecuTorch 執行階段的 Debug 組建,即 executorch_debug framework。為了獲得最佳效能,請務必連結到交付項目的 Release 版本(沒有 _debug 後綴的版本),這些版本已移除所有日誌記錄的額外負荷。

整合

Swift Package Manager

預先建置的 ExecuTorch 執行階段、後端和核心可以作為 Swift PM 套件使用。

Xcode

在 Xcode 中,前往 File > Add Package Dependencies。將 ExecuTorch repo 的 URL 貼到搜尋欄中並選取它。請務必將分支名稱變更為所需的 ExecuTorch 版本,格式為 "swiftpm-",(例如 "swiftpm-0.5.0"),或格式為 "swiftpm-."(例如 "swiftpm-0.5.0-20250130")的分支名稱,以取得特定日期的 nightly build。

然後選擇哪些 ExecuTorch framework 應該連結到哪個目標。

點擊下面的螢幕截圖,觀看示範影片,了解如何新增套件並在 iOS 上執行簡單的 ExecuTorch 模型。

Integrating and Running ExecuTorch on Apple Platforms

CLI

將 ExecuTorch 的套件和目標相依性新增到您的套件檔案,如下所示

// swift-tools-version:5.9
import PackageDescription

let package = Package(
  name: "YourPackageName",
  platforms: [
    .iOS(.v17),
    .macOS(.v10_15),
  ],
  products: [
    .library(name: "YourPackageName", targets: ["YourTargetName"]),
  ],
  dependencies: [
    // Use "swiftpm-<version>.<year_month_day>" branch name for a nightly build.
    .package(url: "https://github.com/pytorch/executorch.git", branch: "swiftpm-0.5.0")
  ],
  targets: [
    .target(
      name: "YourTargetName",
      dependencies: [
        .product(name: "executorch", package: "executorch"),
        .product(name: "backend_xnnpack", package: "executorch"),
        .product(name: "kernels_portable", package: "executorch"),
        // Add other backends and kernels as needed.
      ]),
  ]
)

然後檢查一切是否正常運作

cd path/to/your/package

swift package resolve

# or just build it
swift build

本地建置

整合 ExecuTorch 執行階段的另一種方式是從本機來源建置必要的元件,並與它們連結。此方法更複雜,但絕對可行。

  1. 安裝 Xcode 15+ 和 Command Line Tools

xcode-select --install
  1. Clone ExecuTorch

git clone https://github.com/pytorch/executorch.git --depth 1 --recurse-submodules --shallow-submodules && cd executorch
  1. 設定 Python 3.10+ 並啟動虛擬環境

python3 -m venv .venv && source .venv/bin/activate && pip install --upgrade pip
  1. 安裝所需的相依性,包括建置後端所需的相依性,例如 Core MLMPS (如果您也計劃建置它們)

./install_requirements.sh --pybind coreml mps xnnpack

# Optional dependencies for Core ML backend.
./backends/apple/coreml/scripts/install_requirements.sh

# And MPS backend.
./backends/apple/mps/install_requirements.sh
  1. 安裝 CMake

CMake 網站 下載 macOS 二進位發佈版本,開啟 .dmg 檔案,將 CMake.app 移至 /Applications 目錄,然後執行以下指令以安裝 CMake 命令列工具

sudo /Applications/CMake.app/Contents/bin/cmake-gui --install
  1. 使用提供的腳本來建置 .xcframeworks

./build/build_apple_frameworks.sh --help

例如,以下調用將建置適用於 Apple 平台的所有目前可用的 ExecuTorch 執行階段,以及所有核心和後端

./build/build_apple_frameworks.sh --coreml --mps --xnnpack --custom --optimized --portable --quantized

如果需要,將 --Debug 標誌附加到上述命令,以使用除錯符號建置二進位檔。

建置成功完成後,產生的 framework 可以在 cmake-out 目錄中找到。將它們複製到您的專案並將它們連結到您的目標。

連結

ExecuTorch 在應用程式啟動期間透過在靜態字典中註冊來初始化其後端和核心(運算符)。如果您在執行階段遇到諸如「未註冊的核心」或「未註冊的後端」之類的錯誤,您可能需要明確地強制載入某些元件。在您的 Xcode 建置配置中使用 -all_load-force_load 連結器標誌,以確保元件及早註冊。

以下是 Xcode 配置檔案 (.xcconfig) 的範例

ET_PLATFORM[sdk=iphonesimulator*] = simulator
ET_PLATFORM[sdk=iphoneos*] = ios
ET_PLATFORM[sdk=macos*] = macos

OTHER_LDFLAGS = $(inherited) \
    -force_load $(BUILT_PRODUCTS_DIR)/libexecutorch-$(ET_PLATFORM)-release.a \
    -force_load $(BUILT_PRODUCTS_DIR)/libbackend_coreml-$(ET_PLATFORM)-release.a \
    -force_load $(BUILT_PRODUCTS_DIR)/libbackend_mps-$(ET_PLATFORM)-release.a \
    -force_load $(BUILT_PRODUCTS_DIR)/libbackend_xnnpack-$(ET_PLATFORM)-release.a \
    -force_load $(BUILT_PRODUCTS_DIR)/libkernels_optimized-$(ET_PLATFORM)-release.a \
    -force_load $(BUILT_PRODUCTS_DIR)/libkernels_quantized-$(ET_PLATFORM)-release.a

對於 Debug 建置配置,請將程式庫檔案名稱中的 release 替換為 debug。請記住,即使其他元件是為 Release 建置的,也要在 Debug 模式下連結到 ExecuTorch 執行階段 (libexecutorch),以便在需要時保留日誌。

您可以在 Xcode 中將此類配置檔案分配給您的目標

  1. .xcconfig 檔案新增到您的專案。

  2. 導覽至專案的 Info 標籤。

  3. 在 Release(或 Debug)模式的建置配置中選取配置檔案。

執行階段 API

請查看 C++ 執行階段 API張量 教學課程,以了解更多關於如何載入和執行匯出的模型。建議對 macOS 或 iOS 使用 C++ API,並根據需要使用 Objective-C++ 和 Swift 程式碼進行封裝,以便將其公開給其他元件。請參考 Demo App 作為此類設定的範例。

一旦連結到 executorch 執行階段 framework,目標現在可以匯入所有 ExecuTorch 公用標頭。例如,在 Objective-C++ 中

#import <ExecuTorch/ExecuTorch.h>
#import <executorch/extension/module/module.h>
#import <executorch/extension/tensor/tensor.h>

或在 Swift 中

import ExecuTorch

注意: 匯入 ExecuTorch umbrella 標頭(或 Swift 中的 ExecuTorch 模組)僅提供對日誌記錄 API 的存取權。您仍然需要根據需要明確匯入其他執行階段標頭,例如 module.h。除了下面描述的日誌記錄之外,Objective-C 或 Swift 中不支援其他執行階段 API。

注意: 日誌會在 ExecuTorch framework 的發佈版本中被刪除。為了保留日誌記錄,請在開發期間使用偵錯版本。

日誌記錄

我們為 Objective-C 和 Swift 中的日誌記錄提供額外的 API,作為內部 ExecuTorch 機制的輕量級包裝。若要使用它,只需在 Objective-C 中匯入主要 framework 標頭即可。然後使用 ExecuTorchLog 介面(或 Swift 中的 Log 類別)來訂閱您自己實作的 ExecuTorchLogSink 協定(或 Swift 中的 LogSink)以監聽日誌事件。

#import <ExecuTorch/ExecuTorch.h>
#import <os/log.h>

@interface MyClass : NSObject<ExecuTorchLogSink>
@end

@implementation MyClass

- (instancetype)init {
  self = [super init];
  if (self) {
#if DEBUG
    [ExecuTorchLog.sharedLog addSink:self];
#endif
  }
  return self;
}

- (void)dealloc {
#if DEBUG
  [ExecuTorchLog.sharedLog removeSink:self];
#endif
}

#if DEBUG
- (void)logWithLevel:(ExecuTorchLogLevel)level
           timestamp:(NSTimeInterval)timestamp
            filename:(NSString *)filename
                line:(NSUInteger)line
             message:(NSString *)message {
  NSString *logMessage = [NSString stringWithFormat:@"%@:%lu %@", filename, (unsigned long)line, message];
  switch (level) {
    case ExecuTorchLogLevelDebug:
      os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG, "%{public}@", logMessage);
      break;
    case ExecuTorchLogLevelInfo:
      os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_INFO, "%{public}@", logMessage);
      break;
    case ExecuTorchLogLevelError:
      os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, "%{public}@", logMessage);
      break;
    case ExecuTorchLogLevelFatal:
      os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_FAULT, "%{public}@", logMessage);
      break;
    default:
      os_log(OS_LOG_DEFAULT, "%{public}@", logMessage);
      break;
  }
}
#endif

@end

Swift 版本

import ExecuTorch
import os.log

public class MyClass {
  public init() {
    #if DEBUG
    Log.shared.add(sink: self)
    #endif
  }
  deinit {
    #if DEBUG
    Log.shared.remove(sink: self)
    #endif
  }
}

#if DEBUG
extension MyClass: LogSink {
  public func log(level: LogLevel, timestamp: TimeInterval, filename: String, line: UInt, message: String) {
    let logMessage = "\(filename):\(line) \(message)"
    switch level {
    case .debug:
      os_log(.debug, "%{public}@", logMessage)
    case .info:
      os_log(.info, "%{public}@", logMessage)
    case .error:
      os_log(.error, "%{public}@", logMessage)
    case .fatal:
      os_log(.fault, "%{public}@", logMessage)
    default:
      os_log("%{public}@", logMessage)
    }
  }
}
#endif

注意: 在範例中,當程式碼不是為 Debug 模式建置時,即未定義 DEBUG 巨集或等於零時,會故意刪除日誌。

偵錯

如果您正在連結到 ExecuTorch framework 的 Debug 建置,請設定您的偵錯器以使用偵錯會話中的以下 LLDB 指令正確對應原始碼

settings append target.source-map /executorch <path_to_executorch_source_code>

疑難排解

執行緩慢

請確認匯出的模型使用的是適當的後端,例如 XNNPACK、Core ML 或 MPS。如果已調用正確的後端,但效能問題仍然存在,請確認您連結的是後端執行階段的 Release 版本。

為了獲得最佳效能,請也以 Release 模式連結 ExecuTorch 執行階段。如果需要偵錯,您可以將 ExecuTorch 執行階段保持在 Debug 模式,對效能的影響最小,但保留記錄和偵錯符號。

Swift PM

如果使用 Swift PM 時遇到總和檢查碼不符的錯誤,請使用 Xcode 菜單(File > Packages > Reset Package Caches)或以下指令清除套件快取

rm -rf <YouProjectName>.xcodeproj/project.xcworkspace/xcshareddata/swiftpm \
  ~/Library/org.swift.swiftpm \
  ~/Library/Caches/org.swift.swiftpm \
  ~/Library/Caches/com.apple.dt.Xcode \
  ~/Library/Developer/Xcode/DerivedData

注意: 執行終端機指令前,請確保 Xcode 已完全關閉,以避免與作用中的程序發生衝突。

文件

存取 PyTorch 的完整開發人員文件

查看文件

教學

取得初學者和進階開發人員的深入教學課程

查看教學課程

資源

尋找開發資源並獲得您的問題解答

查看資源