目录

torch::deploy

torch::deploy是一个允许您运行多个嵌入式 Python 的系统 C++ 进程中的解释器,没有共享的全局解释器锁。了解更多 有关内部工作原理的信息,请参阅相关的 arXiv 论文torch::deploy

警告

这是一个原型功能。仅支持 Linux x86,并且 API 可以 更改而不发出警告。

开始

安装torch::deploy

torch::deploy在我们的二进制版本中尚未默认构建,因此要获取 启用了 libtorch 的副本,请按照从源构建 PyTorch 的说明进行操作。torch::deploy

运行 时,您需要指定 ,例如:setup.pyUSE_DEPLOY=1

export CMAKE_PREFIX_PATH=${CONDA_PREFIX:-"$(dirname $(which conda))/../"}
export USE_DEPLOY=1
python setup.py develop

在 Python 中创建模型包

torch::deploy可以加载和运行打包有 的 Python 模型。您可以在文档中了解更多信息。torch.packagetorch.packagetorch.package

现在,让我们创建一个可以在 中加载和运行的简单模型。torch::deploy

from torch.package import PackageExporter
import torchvision

# Instantiate some model
model = torchvision.models.resnet.resnet18()

# Package and export it.
with PackageExporter("my_package.pt") as e:
    e.intern("torchvision.**")
    e.extern("numpy.**")
    e.extern("sys")
    e.extern("PIL.*")
    e.save_pickle("model", "model.pkl", model)

请注意,由于 “numpy”、“sys” 和 “PIL” 被标记为 “extern”,torch.package 将 在加载此软件包的系统上查找这些依赖项。它们不会被打包 与模型。

现在,您的工作目录中应该有一个名为 的文件。my_package.pt

在 C++ 中加载和运行模型

设置一个环境变量(例如 $PATH_TO_EXTERN_PYTHON_PACKAGES)以向解释器指示 其中可以找到外部 Python 依赖项。在下面的示例中, site-packages 的 conda 环境。

export PATH_TO_EXTERN_PYTHON_PACKAGES= \
    "~/anaconda/envs/deploy-example-env/lib/python3.8/site-packages"

让我们创建一个最小的 C++ 程序来加载模型。

#include <torch/csrc/deploy/deploy.h>
#include <torch/csrc/deploy/path_environment.h>
#include <torch/script.h>
#include <torch/torch.h>

#include <iostream>
#include <memory>

int main(int argc, const char* argv[]) {
    if (argc != 2) {
        std::cerr << "usage: example-app <path-to-exported-script-module>\n";
        return -1;
    }

    // Start an interpreter manager governing 4 embedded interpreters.
    std::shared_ptr<torch::deploy::Environment> env =
        std::make_shared<torch::deploy::PathEnvironment>(
            std::getenv("PATH_TO_EXTERN_PYTHON_PACKAGES")
        );
    torch::deploy::InterpreterManager manager(4, env);

    try {
        // Load the model from the torch.package.
        torch::deploy::Package package = manager.loadPackage(argv[1]);
        torch::deploy::ReplicatedObj model = package.loadPickle("model", "model.pkl");
    } catch (const c10::Error& e) {
        std::cerr << "error loading the model\n";
        std::cerr << e.msg();
        return -1;
    }

    std::cout << "ok\n";
}

这个小程序介绍了 的许多核心概念。torch::deploy

一个独立的 Python 集合的抽象 解释器,允许您在运行代码时对它们进行负载均衡。InterpreterManager

PathEnvironment用于指定 Python 的位置 软件包,这些软件包是外部的,但对于您的模型来说是必需的。

使用该方法,您可以从磁盘加载 a 并使其可供所有解释器使用。InterpreterManager::loadPackagetorch.package

Package::loadPickle允许您检索特定的 Python 对象 ,就像我们之前保存的 ResNet 模型一样。

最后,模型本身是一个 .这是 在多个解释器之间复制的对象。当您互动时 替换为 a (例如,通过调用 ),它将选择 一个免费的解释器来执行该交互。ReplicatedObjReplicatedObjforward

构建和运行应用程序

在您的系统上找到 libtorch_deployinterpreter.o。这应该是 在从源代码构建 PyTorch 时构建。在同一个 PyTorch 目录中,找到 Deploy source files.将这些位置设置为构建的环境变量。 下面显示了在系统中找到这些区域的示例。

export DEPLOY_INTERPRETER_PATH="/pytorch/build/torch/csrc/deploy/"
export DEPLOY_SRC_PATH="/pytorch/torch/csrc/deploy/"

与积极开发一样,这些手动步骤将被删除 很快。torch::deploy

假设上述C++程序存储在名为 example-app.cpp 的文件中,则 最小CMakeLists.txt文件如下所示:

cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
project(deploy_tutorial)

find_package(fmt REQUIRED)
find_package(Torch REQUIRED)

add_library(torch_deploy_internal STATIC
    ${DEPLOY_INTERPRETER_PATH}/libtorch_deployinterpreter.o
    ${DEPLOY_DIR}/deploy.cpp
    ${DEPLOY_DIR}/loader.cpp
    ${DEPLOY_DIR}/path_environment.cpp
    ${DEPLOY_DIR}/elf_file.cpp)

# for python builtins
target_link_libraries(torch_deploy_internal PRIVATE
    crypt pthread dl util m z ffi lzma readline nsl ncursesw panelw)
target_link_libraries(torch_deploy_internal PUBLIC
    shm torch fmt::fmt-header-only)
caffe2_interface_library(torch_deploy_internal torch_deploy)

add_executable(example-app example.cpp)
target_link_libraries(example-app PUBLIC
    "-Wl,--no-as-needed -rdynamic" dl torch_deploy "${TORCH_LIBRARIES}")

目前,需要构建为静态库。 为了正确链接到静态库,该实用程序用于适当地设置和取消设置标志。torch::deploycaffe2_interface_library--whole-archive

此外,链接到可执行文件时需要该标志 确保将符号导出到动态表,使其可访问 部署到 deploy 解释器(动态加载)。-rdynamic

最后一步是配置和构建项目。假设我们的代码 目录的布局如下:

example-app/
    CMakeLists.txt
    example-app.cpp

现在,我们可以运行以下命令从文件夹中构建应用程序:example-app/

mkdir build
cd build
# Point CMake at the built version of PyTorch we just installed.
cmake -DCMAKE_PREFIX_PATH="$(python -c 'import torch.utils; print(torch.utils.cmake_prefix_path)')" .. \
    -DDEPLOY_INTERPRETER_PATH="$DEPLOY_INTERPRETER_PATH" \
    -DDEPLOY_DIR="$DEPLOY_DIR"
cmake --build . --config Release

现在我们可以运行我们的应用程序:

./example-app /path/to/my_package.pt

在 C++ 中执行forward

一旦您用 C++ 加载了模型,则很容易执行它:

// Create a vector of inputs.
std::vector<torch::jit::IValue> inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));

// Execute the model and turn its output into a tensor.
at::Tensor output = model(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';

值得注意的是,模型的 forward 函数在 Python 中执行,在嵌入式 CPython 解释器。请注意,该模型是 ,这意味着 ,您可以从多个线程调用,并且 forward 方法将 在多个独立解释器上执行,没有全局解释器 锁。ReplicatedObjmodel()

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源