ExecuTorch 的高階架構與組件¶
本頁描述 ExecuTorch 的技術架構及其個別組件。本文檔適用於將 PyTorch 模型部署到邊緣裝置的工程師。
背景
為了針對具有不同硬體、關鍵電源需求和即時處理需求的設備端 AI,單一的整體解決方案並不實際。 相反,我們需要一個模組化、分層且可擴展的架構。 ExecuTorch 定義了一個精簡的工作流程來準備 (匯出、轉換和編譯) 和執行 PyTorch 程式,具有固定的開箱即用預設組件和明確定義的客製化進入點。 此架構極大地提高了可移植性,使工程師能夠使用高效能、輕量級、跨平台的執行階段,輕鬆整合到不同的裝置和平台中。
概觀¶
將 PyTorch 模型部署到設備端分為三個階段:程式準備、執行階段準備和程式執行,如下圖所示,並帶有一些使用者進入點。我們將在本文件中分別討論每個步驟。
圖 1. 此圖說明了三個階段 - 程式準備、執行階段準備和程式執行。
程式準備¶
ExecuTorch 將 PyTorch 的靈活性和可用性擴展到邊緣裝置。它利用 PyTorch 2 編譯器和匯出功能 (TorchDynamo、AOTAutograd、Quantization、dynamic shapes、control flow 等) 來準備 PyTorch 程式,以便在裝置上執行。
程式準備通常簡稱為 AOT (ahead-of-time),因為對程式的匯出、轉換和編譯是在最終使用 C++ 撰寫的 ExecuTorch 執行階段執行之前完成的。 為了擁有輕量級的執行階段並減少執行中的額外負擔,我們盡可能將工作推送到 AOT。
從程式原始碼開始,以下是您完成程式準備所要經歷的步驟。
程式原始碼¶
匯出¶
為了將程式部署到裝置,工程師需要有一個圖形表示,以便編譯模型以在各種後端上執行。使用 torch.export()
,會使用 ATen 方言產生一個 EXIR (export intermediate representation,匯出中間表示)。 所有 AOT 編譯都基於此 EXIR,但沿著降低路徑可以有多種方言,如下詳述。
ATen 方言。 PyTorch Edge 基於 PyTorch 的 Tensor 函式庫 ATen,它具有用於有效執行的明確協定。 ATen 方言是由完全符合 ATen 的 ATen 節點表示的圖形。 允許使用自訂運算子,但必須向分派器註冊。 它是扁平的,沒有模組層次結構 (較大模組中的子模組),但原始碼和模組層次結構保留在元資料中。 此表示也是 autograd 安全的。
或者,可以在轉換為 Core ATen 之前將量化 (quantization),無論是 QAT (quantization-aware training,量化感知訓練) 還是 PTQ (post training quantization,訓練後量化) 應用於整個 ATen 圖形。 量化有助於減少模型大小,這對於邊緣裝置非常重要。
Core ATen 方言。 ATen 有數千個運算子。 對於某些基本轉換和核心函式庫實作來說,這並非理想選擇。 ATen 方言圖中的運算子會分解為基本運算子,以便運算子集 (op set) 更小,並且可以應用更多基本轉換。 Core ATen 方言也可以序列化並轉換為 Edge 方言,如下詳述。
邊緣編譯¶
上面討論的匯出過程在一個與最終執行程式碼的邊緣裝置無關的圖形上運作。 在邊緣編譯步驟中,我們處理特定於 Edge 的表示。
Edge 方言。 所有運算子都符合具有 dtype 和記憶體配置資訊 (表示為
dim_order
) 的 ATen 運算子,或是已註冊的自訂運算子。 純量會轉換為 Tensor。 這些規範允許後續步驟專注於較小的 Edge 域。 此外,它還支援基於特定 dtypes 和記憶體配置的選擇性建置。
使用 Edge 方言,有兩種針對目標的進一步降低圖形到後端方言的方法。 此時,特定硬體的委派可以執行許多操作。 例如,iOS 上的 Core ML、Qualcomm 上的 QNN 或 Arm 上的 TOSA 可以重寫圖形。 此層級的選項包括
後端委派。 將圖形 (完整或部分) 編譯到特定後端的進入點。 編譯的圖形在此轉換期間會與語意上等效的圖形交換。 編譯的圖形稍後將卸載到後端 (又名
delegated
),以便在執行階段提高效能。使用者定義的傳遞。 使用者也可以執行特定於目標的轉換。 很好的例子是核心融合、非同步行為、記憶體配置轉換等。
編譯為 ExecuTorch 程式¶
上面的 Edge 程式適用於編譯,但不適用於執行階段環境。 設備端部署工程師可以降低圖形,以便執行階段可以有效地載入和執行它。
在大多數 Edge 環境中,動態記憶體分配/釋放會產生顯著的效能和功耗開銷。 可以使用 AOT 記憶體規劃和靜態執行圖來避免它。
ExecuTorch 執行階段是靜態的 (就圖形表示而言,但仍支援控制流程和動態形狀)。 為了避免輸出建立和傳回,所有函數式運算子表示都會轉換為 out 變體 (輸出作為引數傳遞)。
或者,使用者可以應用自己的記憶體規劃演算法。 例如,嵌入式系統可能具有特定的記憶體層次結構。 使用者可以針對該記憶體層次結構進行客製化的記憶體規劃。
程式會以我們的 ExecuTorch 執行階段可以識別的格式發出。
最後,可以將發出的程式序列化為 flatbuffer 格式。
執行階段準備¶
有了序列化的程式,以及提供的核心函式庫 (用於運算子呼叫) 或後端函式庫 (用於委派呼叫),模型部署工程師現在可以準備程式以供執行階段使用。
ExecuTorch 具有 選擇性建置 API,可建置僅連結到程式使用的核心的執行階段,這可以在產生的應用程式中顯著節省二進位大小。
程式執行¶
ExecuTorch 執行期是以 C++ 撰寫,並具有最少的依賴性,以實現可移植性和執行效率。由於程式是經過充分準備的 AOT (Ahead-Of-Time) 編譯,核心執行期組件非常精簡,包含:
平台抽象層
日誌紀錄以及可選擇的效能分析 (Profiling)
執行資料類型
核心 (Kernel) 和後端 (Backend) 註冊表
記憶體管理
Executor 是載入和執行程式的進入點。執行會從這個非常精簡的執行期觸發對應的運算子核心 (operator kernels) 或後端執行。
開發者工具¶
使用者應該能夠有效地從研究到生產環境。生產力對於使用者創作、最佳化和部署模型至關重要。我們提供 ExecuTorch 開發者工具 來提高生產力。開發者工具不在圖表中。相反地,它是一組涵蓋開發者在所有三個階段工作流程的工具。
在程式準備和執行期間,使用者可以使用 ExecuTorch 開發者工具來分析、除錯或視覺化程式。由於端到端流程都在 PyTorch 生態系統中,使用者可以將效能資料與圖形視覺化以及對程式原始碼和模型層級結構的直接參考進行關聯和顯示。我們認為這是快速迭代和將 PyTorch 程式降低到邊緣設備和環境的關鍵組件。