(原型) 基于追踪的选择性构建移动解释器在Android和iOS中¶
创建于:2021年10月20日 | 最后更新:2022年1月12日 | 最后验证:2024年11月5日
作者: 陈莱 <https://github.com/cccclai>, 德鲁夫·马塔尼 <https://github.com/dhruvbird>
警告
基于追踪的选择性构建原型功能以最小化库大小。由于追踪结果依赖于模型输入和追踪环境,如果追踪器在与移动解释器不同的环境中运行,操作符列表可能与实际使用的操作符列表不同,并且可能会引发缺少操作符的错误。
介绍¶
本教程介绍了一种新的自定义构建移动解释器的方法,以进一步优化移动解释器的大小。它将编译二进制文件中包含的操作符集限制为目标模型实际需要的操作符集。这是一种减少PyTorch移动部署二进制文件大小的技术。基于跟踪的选择性构建使用特定的代表性输入运行模型,并记录调用了哪些操作符。然后构建仅包含这些操作符。
以下是使用基于追踪的选择性方法来构建自定义移动解释器的过程。
使用捆绑输入准备模型
import numpy as np
import torch
import torch.jit
import torch.utils
import torch.utils.bundled_inputs
from PIL import Image
from torchvision import transforms
# Step 1. Get the model
model = torch.hub.load('pytorch/vision:v0.7.0', 'deeplabv3_resnet50', pretrained=True)
model.eval()
scripted_module = torch.jit.script(model)
# Export full jit version model (not compatible lite interpreter), leave it here for comparison
scripted_module.save("deeplabv3_scripted.pt")
# Export lite interpreter version model (compatible with lite interpreter)
# path = "<base directory where models are stored>"
scripted_module._save_for_lite_interpreter(f"${path}/deeplabv3_scripted.ptl")
model_file = f"${path}/deeplabv3_scripted.ptl"
# Step 2. Prepare inputs for the model
input_image_1 = Image.open(f"${path}/dog.jpg")
preprocess = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
input_tensor_1 = preprocess(input_image_1)
input_batch_1 = input_tensor_1.unsqueeze(0) # create a mini-batch as expected by the model
scripted_module = torch.jit.load(model_file)
scripted_module.forward(input_batch_1) # optional, to validate the model can run with the input_batch_1
input_image_2 = Image.open(f"${path}/deeplab.jpg")
input_tensor_2 = preprocess(input_image_2)
input_batch_2 = input_tensor_2.unsqueeze(0) # create a mini-batch as expected by the model
scripted_module = torch.jit.load(model_file)
scripted_module.forward(input_batch_2) # optional, to validate the model can run with the input_batch_2
# Step 3. Bundle the model with the prepared input from step2. Can bundle as many input as possible.
bundled_model_input = [
(torch.utils.bundled_inputs.bundle_large_tensor(input_batch_1), ),
(torch.utils.bundled_inputs.bundle_large_tensor(input_batch_2), )]
bundled_model = torch.utils.bundled_inputs.bundle_inputs(scripted_module, bundled_model_input)
bundled_model._save_for_lite_interpreter(f"${path}/deeplabv3_scripted_with_bundled_input.ptl")
构建追踪器
MACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ MAX_JOBS=16 TRACING_BASED=1 python setup.py develop
使用捆绑输入的模型运行追踪器
./build/bin/model_tracer --model_input_path ${path}/deeplabv3_scripted_with_bundled_input.ptl --build_yaml_path ${path}/deeplabv3_scripted.yaml
安卓¶
获取Android中的图像分割演示应用程序:https://github.com/pytorch/android-demo-app/tree/master/ImageSegmentation
基于追踪的构建libtorch lite for android: 通过运行以下命令为所有4种android abi(
armeabi-v7a,arm64-v8a,x86,x86_64)构建libtorch for android。
SELECTED_OP_LIST=${path}/deeplabv3_scripted.yaml TRACING_BASED=1 ./scripts/build_pytorch_android.sh
如果将在Pixel 4模拟器上使用x86进行测试,请使用命令BUILD_LITE_INTERPRETER=1 ./scripts/build_pytorch_android.sh x86来指定abi以节省构建时间。
SELECTED_OP_LIST=${path}/deeplabv3_scripted.yaml TRACING_BASED=1 ./scripts/build_pytorch_android.sh x86
构建完成后,它将显示库路径:
BUILD SUCCESSFUL in 55s
134 actionable tasks: 22 executed, 112 up-to-date
+ find /Users/chenlai/pytorch/android -type f -name '*aar'
+ xargs ls -lah
-rw-r--r-- 1 chenlai staff 13M Feb 11 11:48 /Users/chenlai/pytorch/android/pytorch_android/build/outputs/aar/pytorch_android-release.aar
-rw-r--r-- 1 chenlai staff 36K Feb 9 16:45 /Users/chenlai/pytorch/android/pytorch_android_torchvision/build/outputs/aar/pytorch_android_torchvision-release.aar
在ImageSegmentation应用中使用从源代码构建的PyTorch Android库:在路径中创建一个名为libs的文件夹,从仓库根目录开始的路径将是ImageSegmentation/app/libs。将pytorch_android-release复制到路径
ImageSegmentation/app/libs/pytorch_android-release.aar。将pytorch_android_torchvision(从Pytorch Android Torchvision Nightly下载)复制到路径ImageSegmentation/app/libs/pytorch_android_torchvision.aar。更新ImageSegmentation/app/build.gradle的dependencies部分为
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation(name:'pytorch_android-release', ext:'aar')
implementation(name:'pytorch_android_torchvision', ext:'aar')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.facebook.fbjni:fbjni-java-only:0.0.3'
}
更新 所有项目 部分在 ImageSegmentation/build.gradle 中为
allprojects {
repositories {
google()
jcenter()
flatDir {
dirs 'libs'
}
}
}
测试应用: 在Android Studio中构建并运行ImageSegmentation应用
iOS¶
获取iOS上的ImageSegmentation演示应用程序:https://github.com/pytorch/ios-demo-app/tree/master/ImageSegmentation
为iOS构建libtorch lite:
SELECTED_OP_LIST=${path}/deeplabv3_scripted.yaml TRACING_BASED=1 IOS_PLATFORM=SIMULATOR ./scripts/build_ios.sh
从项目中移除Cocoapods(仅当您运行了pod install时才需要此步骤):
pod deintegrate
将ImageSegmentation演示应用程序与自定义构建的库链接:
在XCode中打开你的项目,进入项目目标的构建阶段 - 使用库链接二进制文件,点击+号并添加位于build_ios/install/lib的所有库文件。导航到项目的构建设置,将头文件搜索路径的值设置为build_ios/install/include,并将库搜索路径的值设置为build_ios/install/lib。 在构建设置中,搜索其他链接器标志。在-all_load下方添加一个自定义链接器标志。 最后,通过选择构建设置,搜索启用Bitcode,并将其值设置为否来为目标禁用Bitcode。
在Xcode中构建并测试应用程序。
结论¶
在本教程中,我们展示了一种新的自定义构建PyTorch高效移动解释器的方法——基于追踪的选择性构建,适用于Android和iOS应用程序。
我们通过一个图像分割示例展示了如何将输入打包到模型中,通过使用打包输入跟踪模型生成操作符列表,并从跟踪结果中的操作符列表构建自定义的torch库。
自定义构建仍在开发中,我们将在未来继续改进其大小。但请注意,API在未来的版本中可能会发生变化。
感谢阅读!一如既往,我们欢迎任何反馈,所以请在这里创建一个问题 <https://github.com/pytorch/pytorch/issues>`。
了解更多
要了解更多关于PyTorch Mobile的信息,请参考PyTorch Mobile主页<https://pytorch.org/mobile/home/>
要了解更多关于图像分割的信息,请参考Android上的图像分割DeepLabV3教程<https://pytorch.org/tutorials/beginner/deeplabv3_on_android.html>_