尧图精选

PyTorch Android 构建与集成指南:从 Maven 依赖到源码编译 libpytorch.so 的完整实践

🕒 发布时间:2026/9/5 19:14:07 📁 来源:尧图网络
PyTorch Android 构建与集成指南从 Maven 依赖到源码编译 libpytorch.so 的完整实践【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorchPyTorch 的 Android 集成位于仓库的 android/ 目录它是把 LibTorch 的 C 推理能力通过 JNI 桥接层libpytorch.so/libpytorch_jni_lite.so暴露给 Android 应用的完整工程。本文基于 android/README.md 展开覆盖 Android 官方发布的 Release/Nightly 依赖引入方式、从源码编译 libtorch 并打包成 AAR 的完整流程以及在自己的 Android 原生构建中直接链接预编译 libtorch 的 CMake 方案并深入源码讲解BUILD_LITE_INTERPRETER、ABI_FILTERS、fbjni 桥接层等关键配置背后的实际实现。一、Android 集成的整体形态lite 与 full jit 两种构建在阅读具体操作前先理解 android 目录的模块划分。settings.gradle 声明了四个模块include :app, :pytorch_android, :pytorch_android_torchvision, :pytorch_host, :test_app project(:pytorch_android_torchvision).projectDir file(pytorch_android_torchvision) project(:pytorch_host).projectDir file(pytorch_android/host)pytorch_android核心库产出pytorch_android.aar内含 Java API、JNI 桥接层和各 ABI 的 native 库pytorch_android_torchvision视觉模型支持库产出pytorch_android_torchvision.aarpytorch_host宿主Host侧构建用于在非 Android 平台上验证 JNI 层。整个集成最关键的设计是lite interpreter 与 full jit 二选一的构建模式。在 pytorch_android/CMakeLists.txt 中可以看到option(BUILD_LITE_INTERPRETER Master flag to build pytorch_jni_lite ON) if(BUILD_LITE_INTERPRETER) project(pytorch_jni_lite CXX) set(PYTORCH_JNI_TARGET pytorch_jni_lite) else() project(pytorch_jni CXX) set(PYTORCH_JNI_TARGET pytorch_jni) endif()即开关打开时编译pytorch_jni_liteLite Interpreter 后端对应 Maven 坐标中的pytorch_android_lite关闭时编译pytorch_jni完整 JIT对应pytorch_android。CMake 根据该开关选择编译的源码文件也不同if(BUILD_LITE_INTERPRETER) file(GLOB pytorch_android_SOURCES ${pytorch_android_DIR}/pytorch_jni_lite.cpp ${pytorch_android_DIR}/pytorch_jni_common.cpp ${pytorch_android_DIR}/pytorch_jni_common.h ) else() file(GLOB pytorch_android_SOURCES ${pytorch_android_DIR}/pytorch_jni_jit.cpp ${pytorch_android_DIR}/pytorch_jni_common.cpp ${pytorch_android_DIR}/pytorch_jni_common.h ) endif()pytorch_android/build.gradle 则通过环境变量BUILD_LITE_INTERPRETER同步控制 Java 侧的排除逻辑当设置为0时构建 full jit 版本排除LiteModuleLoader.java和LiteNativePeer.java并只保留 full jit 的 instrumented tests默认非0则构建 lite 版本。这就是为什么 README 中 Maven 依赖要分*_lite与常规两种坐标——它们由同一套源码、同一个开关产出。此外CMakeLists 中对 Android 平台启用了 Vulkan 支持if(ANDROID_ABI) set(USE_VULKAN ON)并通过import_static_lib把libtorch、libtorch_cpu、libc10、libnnpack、libXNNPACK、libpytorch_qnnpack、libpthreadpool、libeigen_blas、libcpuinfo、libclog等静态库以--whole-archive方式整体链入最终的libpytorch_jni(_lite).so这就是 Android 端单一 .so 自包含的产物形态。对于 Android 演示应用官方推荐参考 ExecuTorch 示例仓库中的 DeepLabV3Demometa-pytorch/executorch-examples的dl3/android/DeepLabV3Demo目录问题反馈渠道为官方 Discord。注意 ExecuTorch 是 PyTorch 移动端生态的演进方向本目录的构建/发布流程面向 PyTorch Android 库本身。二、引入官方发布产物Release 与 Nightly2.1 Release 版本稳定版发布到 jcenterMaven 坐标为org.pytorch:pytorch_android*:版本。android/gradle.properties 确认了发布元数据VERSION_NAME2.2.0-SNAPSHOT GROUPorg.pytorch MAVEN_GROUPorg.pytorch SONATYPE_STAGING_PROFILEorgpytorchGROUP/MAVEN_GROUPorg.pytorch与 README 中的依赖坐标一致。引入方式repositories { jcenter() } # lite interpreter build dependencies { implementation org.pytorch:pytorch_android_lite:1.10.0 implementation org.pytorch:pytorch_android_torchvision_lite:1.10.0 } # full jit build dependencies { implementation org.pytorch:pytorch_android:1.10.0 implementation org.pytorch:pytorch_android_torchvision:1.10.0 }选型建议纯手机端 TorchScript 推理、追求包体积与加载性能时选 lite需要在设备上运行完整 TorchScript依赖完整 JIT 能力时选 full jit。2.2 Nightly快照版本master分支的夜间构建会发布到 Sonatype Central 快照仓库。由于快照仓库不会出现在默认仓库列表中必须显式声明repositories { maven { url https://central.sonatype.com/repository/maven-snapshots/ } } # lite interpreter build dependencies { implementation org.pytorch:pytorch_android_lite:1.12.0-SNAPSHOT implementation org.pytorch:pytorch_android_torchvision_lite:1.12.0-SNAPSHOT } # full jit build dependencies { implementation org.pytorch:pytorch_android:1.12.0-SNAPSHOT implementation org.pytorch:pytorch_android_torchvision:1.12.0-SNAPSHOT }README 特别强调当前 nightly 版本号不是写死的而是当前目录 android/gradle.properties 中VERSION_NAME的值本文撰写时仓库中该值为2.2.0-SNAPSHOT。升级 pytorch 源码树后快照的语义化版本会随之变化接入 nightly 时应先读gradle.properties确认坐标避免依赖解析失败。发布动作本身由 gradle/release.gradle 完成它引入com.vanniktech.maven-publish插件apply from: rootProject.file(gradle/android_tasks.gradle) apply plugin: com.vanniktech.maven.publish而pytorch_android/build.gradle末尾还注册了sourcesJar任务并把源码 jar 挂到archives工件上保证发布产物附带源码。三、从源码构建 PyTorch Android当你需要定制算子集合、打本地补丁或产出与官方二进制不同的 libtorch 时可以从源码构建。3.1 构建流程总览入口脚本为./scripts/build_pytorch_android.shgit clone https://github.com/pytorch/pytorch.git cd pytorch git submodule update --init --recursive bash ./scripts/build_pytorch_android.shREADME 描述了脚本的三步工作流可以在仓库源码中一一对应为 4 个 Android ABI 构建 libtorcharmeabi-v7a、arm64-v8a、x86、x86_64与 android/gradle.properties 第 1 行ABI_FILTERSarmeabi-v7a,arm64-v8a,x86,x86_64保持一致common.sh 中parse_abis_list函数也硬编码了同一列表并注释要求两边同步建立符号链接把各 ABI 构建产物链接到android/pytorch_android/src/main/jniLibs/${abi}库和android/pytorch_android/src/main/cpp/libtorch_include/${abi}头文件这两个目录正是后续 CMake 构建libpytorch.so时消费的输入见下文 CMakeLists.txt 中的libtorch_include_DIR与import_static_lib在android/pytorch_android下执行 gradleassembleRelease。common.sh 的build_android函数完整实现了第 1、2 步可以逐行印证for abi in $(echo $ABIS_LIST | tr , \n) do ANDROID_BUILD_ROOT$BUILD_ROOT/build_android_$abi ANDROID_ABI$abi \ BUILD_ROOT$ANDROID_BUILD_ROOT \ $PYTORCH_DIR/scripts/build_android.sh \ -DANDROID_CCACHE$(which ccache) \ -DUSE_LITE_INTERPRETER_PROFILEROFF ln -s $ANDROID_BUILD_ROOT/install/lib $LIB_DIR/$abi ln -s $ANDROID_BUILD_ROOT/install/include $INCLUDE_DIR/$abi done注意两个工程细节每个 ABI 独立输出到build_android_$abi且明确注释These directories only contain symbolic links——jniLibs与libtorch_include目录每次构建前会被清空重建rm -rf后mkdir -p所以它们不应被纳入版本管理。另外脚本通过$(which ccache)注入ANDROID_CCACHE加速重复编译并关闭USE_LITE_INTERPRETER_PROFILER以减小体积。3.2 环境要求脚本需要三个环境变量均被 common.sh 中的检查函数强制校验环境变量含义校验逻辑ANDROID_HOMEAndroid SDK 路径check_android_sdk未设置或路径不存在时直接退出ANDROID_NDKAndroid NDK 路径README 建议使用 NDK 21.x由底层scripts/build_android.sh消费GRADLE_HOMEgradle 安装路径仓库实际提供了android/gradlew包装器check_gradle中GRADLE_PATH$PYTORCH_DIR/android/gradlew3.3 验证构建产物构建成功后应能在各模块的build/outputs/aar/下看到 AAR$ find pytorch_android/build/ -type f -name *aar pytorch_android/build/outputs/aar/pytorch_android.aar pytorch_android_torchvision/build/outputs/aar/pytorch_android.aar3.4 在 Android 项目中直接使用本地 AARAAR 可以通过flatDir仓库直接作为 gradle 依赖引入allprojects { repositories { flatDir { dirs libs } } } dependencies { implementation(name:pytorch_android, ext:aar) implementation(name:pytorch_android_torchvision, ext:aar) ... implementation com.facebook.soloader:nativeloader:0.10.5 implementation com.facebook.fbjni:fbjni-java-only:0.2.2 }手动补充传递依赖的原因本地 AAR 方式不会像 Maven 那样自动解析pom.xml中的依赖因此需要显式声明pytorch_android的两个传递依赖。这两个版本的真值来源是 android/build.gradle 的根项目ext定义fbjniJavaOnlyVersion 0.2.2 soLoaderNativeLoaderVersion 0.10.5以及 pytorch_android/build.gradle 中的依赖声明dependencies { implementation com.facebook.fbjni:fbjni-java-only: rootProject.fbjniJavaOnlyVersion implementation com.facebook.soloader:nativeloader: rootProject.soLoaderNativeLoaderVersion ... }即nativeloader:0.10.5负责在运行时 dlopen 各 ABI 的.sofbjni-java-only:0.2.2提供 Java/C 桥接所需的 FBJavaClass 等基础设施——CMake 侧的 JNI 目标也显式链接了 fbjniset(fbjni_DIR .../../libs/fbjni/)后add_subdirectory。另一个值得注意的 AAR 定制点pytorch_android/build.gradle 在afterEvaluate中注册addHeadersToAar任务把src/main/cpp/libtorch_include/abi头文件打进 AAR 的headers/目录getLibtorchHeadersDir取ABI_FILTERS的第一个 ABI。这直接服务于下一节的原生构建链接预编译 libtorch场景。四、从 Maven AAR 链接预编译 libtorch 到自研 Native 代码即使不自行编译 libtorch也可以在自己的 CMake 原生构建中使用 libtorch C API——直接解包官方 AAR 中的头文件与预编译库即可。4.1 Gradle 侧配置在项目的build.gradle中新增一个专用 configuration并注册解包任务android { ... configurations { extractForNativeBuild } ... compileOptions { externalNativeBuild { cmake { arguments -DANDROID_STLc_shared } } } ... externalNativeBuild { cmake { path CMakeLists.txt } } } dependencies { extractForNativeBuild(org.pytorch:pytorch_android:1.10.0) } task extractAARForNativeBuild { doLast { configurations.extractForNativeBuild.files.each { def file it.absoluteFile copy { from zipTree(file) into $buildDir/$file.name include headers/** include jni/** } } } } tasks.whenTaskAdded { task - if (task.name.contains(externalNativeBuild)) { task.dependsOn(extractAARForNativeBuild) } }要点解释与 README 的说明一一对应AAR 内部布局pytorch_android.aar内headers/目录存放 libtorch 头文件jni/$ANDROID_ABI/存放各 ABI 的 native 库对应jniLibs.srcDirs [src/main/jniLibs]与上文addHeadersToAar注入的产物必须使用c_sharedPyTorch 原生库本身以ANDROID_STLc_shared构建若你的模块用其它 STL 变体会出现 C 运行时不兼容/重复符号问题。README 明确要求should useANDROID_STLc_sharedto have only one loaded binary of STL任务依赖注入tasks.whenTaskAdded让所有externalNativeBuild*任务自动依赖解包任务保证 CMake 配置时 headers/jni 已就位。4.2 CMake 侧配置# Relative path of gradle build directory to CMakeLists.txt set(build_DIR ${CMAKE_SOURCE_DIR}/build) file(GLOB PYTORCH_INCLUDE_DIRS ${build_DIR}/pytorch_android*.aar/headers) file(GLOB PYTORCH_LINK_DIRS ${build_DIR}/pytorch_android*.aar/jni/${ANDROID_ABI}) set(BUILD_SUBDIR ${ANDROID_ABI}) target_include_directories(${PROJECT_NAME} PRIVATE ${PYTORCH_INCLUDE_DIRS} ) find_library(PYTORCH_LIBRARY pytorch_jni PATHS ${PYTORCH_LINK_DIRS} NO_CMAKE_FIND_ROOT_PATH) find_library(FBJNI_LIBRARY fbjni PATHS ${PYTORCH_LINK_DIRS} NO_CMAKE_FIND_ROOT_PATH) target_link_libraries(${PROJECT_NAME} ${PYTORCH_LIBRARY} ${FBJNI_LIBRARY})注意事项build_DIR的取值依赖CMakeLists.txt与build.gradle同目录这一默认布局若你的 CMakeLists 位于子目录例如src/main/cpp/需按相对位置调整该路径——这是 README 明确提示的常见坑find_library使用pytorch_jni这一名称对应 full jit 构建的 JNI 库NO_CMAKE_FIND_ROOT_PATH 防止 CMake 在 sysroot 中误匹配fbjni同样从 AAR 的 jni 目录发现避免系统路径污染。4.3 调用 LibTorch C API 的最小示例链接完成后即可在 native 代码中使用 libtorchREADME 给出的完整示例#include string #include ATen/NativeFunctions.h #include torch/script.h namespace pytorch_testapp_jni { namespace { struct JITCallGuard { c10::InferenceMode guard; torch::jit::GraphOptimizerEnabledGuard no_optimizer_guard{false}; }; } void loadAndForwardModel(const std::string modelPath) { JITCallGuard guard; torch::jit::Module module torch::jit::load(modelPath); module.eval(); torch::Tensor t torch::randn({1, 3, 224, 224}); c10::IValue t_out module.forward({t}); } }JITCallGuard这个特殊设置不可省略c10::InferenceMode将本次推理置于推断模式以跳过 autograd 元数据开销torch::jit::GraphOptimizerEnabledGuard no_optimizer_guard{false}关闭图优化器因为移动端加载的 TorchScript 模型通常不需要、也不应再触发图优化。README 同时提醒该 setup 可能随版本演进最新形态应以 android/pytorch_android/src/main/cpp/pytorch_jni_jit.cpp 中官方 JNI 层的调用惯例为准。从源码结构看该文件正是 full jit 构建BUILD_LITE_INTERPRETER0时编译进libpytorch_jni.so的桥接实现与 lite 构建的pytorch_jni_lite.cpp形成对照。五、在 x86 模拟器上运行 instrumented tests官方 CI 通过 android/run_tests.sh 在 x86 模拟器上跑 instrumented tests。脚本逻辑值得借鉴为本地验证流程检查ANDROID_HOME并定位adb$ANDROID_HOME/platform-tools/adb用adb devices统计设备数若为 0DEVICES_COUNT -eq 1输出只含表头则打印完整的手动起机步骤并退出安装系统镜像sdkmanager system-images;android-25;google_apis;x86需要代理时可加--proxyhttp --proxy_hostfwdproxy --proxy_port8080创建 AVDavdmanager create avd --name x86_android25 --package system-images;android-25;google_apis;x86无头无音频启动emulator -avd x86_android25 -no-audio -no-window再adb devices应看到emulator-5554 deviceadb wait-for-device shell while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;等待系统 boot 完成执行gradlew -PABI_FILTERSx86 -p android connectedAndroidTest并用 common.sh 中的retry函数做最多 3 次退避重试sleep 10/20/40 秒——注释说明该测试一轮约 10 分钟失败时会提示参考test/mobile/model_test修复移动侧测试。-PABI_FILTERSx86参数对应ndk { abiFilters ABI_FILTERS.split(,) }的 gradle 属性覆写让测试只针对 x86 ABI 构建与模拟器架构匹配。六、API 文档与延伸阅读PyTorch Android API 的 JavaDoc 见官方 Javadoc模块根构建参数minSdk 21 / targetSdk 28 / AGP 4.1.2 等见 android/build.gradleext { minSdkVersion 21 targetSdkVersion 28 compileSdkVersion 28 buildToolsVersion 28.0.3 ... }android/gradle.properties 中的nativeLibsDoNotStripfalse控制 release 是否保留符号pytorch_android/build.gradle的packagingOptions依据它决定是否doNotStrip **/*.so置为true时会打印 WARNING 并保留 debug 符号仅建议调试期使用android.useAndroidXtrue/android.enableJetifiertrue表明工程运行在 AndroidX Jetifier 体系下。七、总结场景推荐路径关键配置常规接入Maven 依赖jcenter org.pytorch:pytorch_android(_lite):ver尝鲜 masterNightly 快照显式 Sonatype snapshots 仓库 gradle.properties中VERSION_NAME对应的-SNAPSHOT坐标定制算子/本地补丁源码构建scripts/build_pytorch_android.sh 三个环境变量产物为本地 AAR自研 native 代码 官方 libtorchAAR 解包 CMakeextractForNativeBuild任务 ANDROID_STLc_sharedfind_library(pytorch_jni)本地回归验证模拟器 instrumented testsrun_tests.shx86 AVD -PABI_FILTERSx86 connectedAndroidTestPyTorch Android 集成的工程核心可以概括为一句话同一套源码由BUILD_LITE_INTERPRETER开关分化为 lite/jit 两种 JNI 目标libtorch 静态库以--whole-archive方式整体链入单一libpytorch_jni(_lite).so再经 AAR 打包含 jniLibs、headers交付给 Java 层nativeloader 加载 fbjni 桥接。掌握这条主线后无论是选 Maven 坐标、读gradle.properties确认快照版本还是排查 CMake 链接失败STL 变体、build_DIR相对路径、find_library名称都能落到源码层面的确切依据上。【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →