• 文件 >
  • 使用 ExecuTorch 開發者工具來分析模型效能
捷徑

使用 ExecuTorch 開發者工具來分析模型效能

作者: Jack Khuu

本教學將展示如何利用開發者工具來分析模型的完整端到端流程。具體來說,它將:

  1. 產生開發者工具使用的 Artifacts (ETRecordETDump)。

  2. 建立使用這些 Artifacts 的 Inspector 類別。

  3. 利用 Inspector 類別來分析模型分析結果。

先決條件

若要執行本教學,您需要先設定您的 ExecuTorch 環境

產生 ETRecord (選用)

第一步是產生一個 ETRecordETRecord 包含模型圖和元數據,用於將運行時結果 (例如 Profiling) 連結到 Eager 模型。這是透過 executorch.devtools.generate_etrecord 產生的。

executorch.devtools.generate_etrecord 接收一個輸出檔案路徑 (str)、Edge 方言模型 (EdgeProgramManager)、ExecuTorch 方言模型 (ExecutorchProgramManager) 和一個可選的額外模型字典。

在本教學中,使用一個範例模型(如下所示)進行示範。

import copy

import torch
import torch.nn as nn
import torch.nn.functional as F
from executorch.devtools import generate_etrecord

from executorch.exir import (
    EdgeCompileConfig,
    EdgeProgramManager,
    ExecutorchProgramManager,
    to_edge,
)
from torch.export import export, ExportedProgram


# Generate Model
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 5*5 from image dimension
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square, you can specify with a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = torch.flatten(x, 1)  # flatten all dimensions except the batch dimension
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


model = Net()

aten_model: ExportedProgram = export(
    model,
    (torch.randn(1, 1, 32, 32),),
)

edge_program_manager: EdgeProgramManager = to_edge(
    aten_model, compile_config=EdgeCompileConfig(_check_ir_validity=True)
)
edge_program_manager_copy = copy.deepcopy(edge_program_manager)
et_program_manager: ExecutorchProgramManager = edge_program_manager.to_executorch()


# Generate ETRecord
etrecord_path = "etrecord.bin"
generate_etrecord(etrecord_path, edge_program_manager_copy, et_program_manager)

警告

使用者應對 to_edge() 的輸出進行深拷貝 (deepcopy),並將深拷貝傳遞給 generate_etrecord API。這是必需的,因為後續的 to_executorch() 呼叫會進行原地 (in-place) 變更,並且會在此過程中遺失偵錯資料。

產生 ETDump

下一步是產生一個 ETDumpETDump 包含執行 捆綁程式模型 (Bundled Program Model) 的運行時結果。

在本教學中,捆綁程式是從上面的範例模型建立的。

import torch
from executorch.devtools import BundledProgram

from executorch.devtools.bundled_program.config import MethodTestCase, MethodTestSuite
from executorch.devtools.bundled_program.serialize import (
    serialize_from_bundled_program_to_flatbuffer,
)

from executorch.exir import to_edge
from torch.export import export

# Step 1: ExecuTorch Program Export
m_name = "forward"
method_graphs = {m_name: export(model, (torch.randn(1, 1, 32, 32),))}

# Step 2: Construct Method Test Suites
inputs = [[torch.randn(1, 1, 32, 32)] for _ in range(2)]

method_test_suites = [
    MethodTestSuite(
        method_name=m_name,
        test_cases=[
            MethodTestCase(inputs=inp, expected_outputs=getattr(model, m_name)(*inp))
            for inp in inputs
        ],
    )
]

# Step 3: Generate BundledProgram
executorch_program = to_edge(method_graphs).to_executorch()
bundled_program = BundledProgram(executorch_program, method_test_suites)

# Step 4: Serialize BundledProgram to flatbuffer.
serialized_bundled_program = serialize_from_bundled_program_to_flatbuffer(
    bundled_program
)
save_path = "bundled_program.bp"
with open(save_path, "wb") as f:
    f.write(serialized_bundled_program)

使用 CMake(依照這些指示設定 CMake)執行捆綁程式以產生 ETDump

cd executorch
./examples/devtools/build_example_runner.sh
cmake-out/examples/devtools/example_runner --bundled_program_path="bundled_program.bp"

建立 Inspector

最後一步是透過傳入 Artifacts 路徑來建立 Inspector。Inspector 取得 ETDump 的運行時結果,並將它們與 Edge 方言圖的運算子相關聯。

回顧:不需要 ETRecord。如果沒有提供 ETRecord,Inspector 將顯示沒有運算子關聯的運行時結果。

若要視覺化所有運行時事件,請呼叫 Inspector 的 print_data_tabular

from executorch.devtools import Inspector

etrecord_path = "etrecord.bin"
etdump_path = "etdump.etdp"
inspector = Inspector(etdump_path=etdump_path, etrecord=etrecord_path)
inspector.print_data_tabular()
False

使用 Inspector 分析

Inspector 提供了兩種存取擷取資訊的方式:EventBlocksDataFrames。這些媒介讓使用者能夠對其模型效能進行自訂分析。

以下是範例用法,包含 EventBlockDataFrame 方法。

# Set Up
import pprint as pp

import pandas as pd

pd.set_option("display.max_colwidth", None)
pd.set_option("display.max_columns", None)

如果使用者想要原始的 Profiling 結果,他們會執行類似於尋找 addmm.out 事件的原始運行時資料的操作。

for event_block in inspector.event_blocks:
    # Via EventBlocks
    for event in event_block.events:
        if event.name == "native_call_addmm.out":
            print(event.name, event.perf_data.raw)

    # Via Dataframe
    df = event_block.to_dataframe()
    df = df[df.event_name == "native_call_addmm.out"]
    print(df[["event_name", "raw"]])
    print()

如果使用者想要追蹤運算子回到他們的模型程式碼,他們會執行類似於尋找最慢 convolution.out 呼叫的模組層級和堆疊追蹤的操作。

for event_block in inspector.event_blocks:
    # Via EventBlocks
    slowest = None
    for event in event_block.events:
        if event.name == "native_call_convolution.out":
            if slowest is None or event.perf_data.p50 > slowest.perf_data.p50:
                slowest = event
    if slowest is not None:
        print(slowest.name)
        print()
        pp.pprint(slowest.stack_traces)
        print()
        pp.pprint(slowest.module_hierarchy)

    # Via Dataframe
    df = event_block.to_dataframe()
    df = df[df.event_name == "native_call_convolution.out"]
    if len(df) > 0:
        slowest = df.loc[df["p50"].idxmax()]
        print(slowest.event_name)
        print()
        pp.pprint(slowest.stack_traces)
        print()
        pp.pprint(slowest.module_hierarchy)

如果使用者想要模組的總運行時間,他們可以使用 find_total_for_module

print(inspector.find_total_for_module("L__self__"))
print(inspector.find_total_for_module("L__self___conv2"))
0.0
0.0

注意:find_total_for_moduleInspector 的一個特殊的 First Class 方法。

結論

在本教學中,我們了解了使用 ExecuTorch 開發者工具使用 ExecuTorch 模型所需的步驟。它還展示了如何使用 Inspector API 來分析模型運行結果。

文件

存取 PyTorch 的完整開發者文件

檢視文件

教學

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

檢視教學課程

資源

尋找開發資源並取得問題解答

檢視資源