• 文件 >
  • 大規模部署的功能
捷徑

大規模部署的功能

此筆記討論了幾個擴充點和技巧,這些點和技巧在較大的系統中運行 PyTorch 或在較大的組織中使用 PyTorch 運行多個系統時可能會很有用。

它不涵蓋將模型部署到生產環境的主題。請查看 torch.jit 或相關的教學文件。

此筆記假設您在組織內部從原始碼建置 PyTorch,或者能夠靜態連結額外的程式碼,以便在使用 PyTorch 時載入。因此,許多 hook 都以 C++ API 的形式公開,可以在一個集中位置觸發,例如在靜態初始化程式碼中。

全伺服器群組 Operator 分析

PyTorch 內建 torch.autograd.profiler,能夠按需測量個別 operator 所花費的時間。可以使用相同的機制,針對任何執行 PyTorch 的進程進行「始終開啟」的測量。這對於收集有關在給定進程中或跨整個機器集合運行的 PyTorch 工作負載的資訊可能很有用。

可以使用 torch::addGlobalCallback 新增任何 operator 調用的新回呼。Hook 將使用 torch::RecordFunction 結構呼叫,該結構描述了調用上下文(例如 name)。如果啟用,RecordFunction::inputs() 包含以 torch::IValue 變體類型表示的函數參數。請注意,輸入記錄的開銷相對較高,因此必須明確啟用。

Operator 回呼還可以存取 c10::ThreadLocalDebugInfo::get() 介面,該介面傳回指向保存除錯資訊的結構的指標。此除錯資訊可以稍早使用 at::DebugInfoGuard 物件設定。除錯資訊會透過正向傳遞(包括非同步 fork 任務)和反向傳遞傳播,並且可用於將有關執行環境(例如,模型 ID)的額外資訊從應用程式的較高層傳遞到 operator 回呼。

調用回呼會增加一些開銷,因此通常僅隨機取樣 operator 調用會很有用。可以使用傳遞到 torch::addGlobalCallback 的可選取樣率在每個回呼的基礎上啟用此功能。

請注意,addGlobalCallback 不是執行緒安全的,只能在沒有 PyTorch operator 運作時呼叫。通常,在初始化期間呼叫它們一次是個好主意。

這是一個範例

// Called somewhere in the program beginning
void init() {
    // Sample one in a hundred operator runs randomly
    addGlobalCallback(
      RecordFunctionCallback(
        &onFunctionEnter,
        &onFunctionExit)
      .needsInputs(true)
      .samplingProb(0.01)
    );
    // Note, to enable observers in the model calling thread,
    // call enableRecordFunction() in the thread before running a model
}

void onFunctionEnter(const RecordFunction& fn) {
    std::cerr << "Before function " << fn.name()
              << " with " << fn.inputs().size() << " inputs" << std::endl;
}

void onFunctionExit(const RecordFunction& fn) {
    std::cerr << "After function " << fn.name();
}

API 使用記錄

在更廣泛的生態系統中運行時,例如在託管的作業排程器中,追蹤哪些二進位檔案調用特定的 PyTorch API 通常很有用。存在簡單的檢測,注入到幾個重要的 API 點,會觸發給定的回呼。因為通常 PyTorch 是在一次性的 Python 腳本中調用,所以對於每個 API,回呼僅針對給定進程觸發一次。

c10::SetAPIUsageHandler 可用於註冊 API 使用檢測處理常式。傳遞的參數將會是識別已使用點的「API 金鑰」,例如 python.import 用於 PyTorch 擴充匯入,或 torch.script.compile 如果觸發了 TorchScript 編譯。

SetAPIUsageLogger([](const std::string& event_name) {
    std::cerr << "API was used: " << event_name << std::endl;
});

開發人員注意事項:可以在程式碼中使用 C10_LOG_API_USAGE_ONCE("my_api") 在 C++ 中或 torch._C._log_api_usage_once("my.api") 在 Python 中新增新的 API 觸發點。

將元資料附加到已儲存的 TorchScript 模型

TorchScript 模組可以儲存為歸檔檔案,該檔案將序列化的參數和模組程式碼捆綁為 TorchScript(請參閱 torch.jit.save())。將額外資訊與模型捆綁在一起通常很方便,例如,模型生產者的描述或輔助成品。

這可以透過將 _extra_files 參數傳遞給 torch.jit.save()torch::jit::load 來儲存和檢索儲存過程中的任意二進位 Blob 來實現。由於 TorchScript 檔案是常規 ZIP 歸檔,因此額外資訊會以常規檔案的形式儲存在歸檔的 extra/ 目錄中。

還有一個全域 hook 允許將額外檔案附加到目前進程中產生的任何 TorchScript 歸檔。將模型標記為生產者元資料可能很有用,類似於數位相機產生的 JPEG 元資料。範例用法可能如下所示

SetExportModuleExtraFilesHook([](const Module&) {
    ExtraFilesMap files;
    files["producer_info.json"] = "{\"user\": \"" + getenv("USER") + "\"}";
    return files;
});

建置環境考量

TorchScript 的編譯需要存取原始的 Python 檔案,因為它使用 Python 的 inspect.getsource 呼叫。在某些生產環境中,可能需要明確地將 .py 檔案與預先編譯的 .pyc 一起部署。

常見的擴充點

PyTorch API 通常是鬆散耦合的,並且很容易用專門的版本替換元件。常見的擴充點包括

文件

存取 PyTorch 的完整開發者文件

檢視文件

教學

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

檢視教學

資源

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

檢視資源