Android NDK加载TensorFlow冻结模型时算子未注册问题求助
解决TensorFlow C++ API在Android上的未知算子错误
你遇到的PopulationCount这类未知算子错误,核心原因是你当前使用的**精简版TensorFlow静态库(libtensorflow-core.a)**默认只包含了常用算子集合,像PopulationCount这类不常用算子并没有被编译进去——从你的CMake脚本里的-DIS_SLIM_BUILD编译宏也能看出来,这个宏就是开启精简构建的开关。
下面分两种场景给你解决方案:
一、修复当前静态库方案的算子缺失问题
1. 关闭精简构建,全量编译TensorFlow库
最简单的方式是去掉CMake脚本里的-DIS_SLIM_BUILD编译选项,然后重新运行build_android_all.sh构建armeabi-v7a架构的依赖。这样生成的libtensorflow-core.a会包含所有TensorFlow算子,自然就能解决未知算子的问题,代价是库文件体积会明显增大。
2. 手动添加单个缺失算子
如果不想全量编译(担心库体积过大),可以单独把缺失的算子源码加入你的JNI项目:
- 找到TensorFlow源码中
PopulationCount算子的实现文件:tensorflow/core/kernels/population_count_op.cc - 把这个文件复制到你的项目
src/main/cpp目录下 - 修改CMake的
add_library部分,把这个源文件加进去:
add_library( # Sets the name of the library. ${PROJECT_NAME} SHARED src/main/cpp/native-lib.h src/main/cpp/native-lib.cpp src/main/cpp/TensorflowInferenceHandler.h src/main/cpp/TensorflowInferenceHandler.cpp src/main/cpp/population_count_op.cc # 新增算子源文件 )
- 确保你的
include_directories已经包含了tensorflow/core/kernels所在的路径,或者直接在population_count_op.cc里调整头文件引用路径。
二、切换到动态库tensorflow_inference.so的方案
如果静态库的方式实在不好调整,你可以改用TensorFlow官方的预编译动态库,或者自己编译完整的tensorflow_inference.so:
1. 使用官方预编译动态库
TensorFlow官方提供了针对Android各架构的预编译tensorflow_inference.so,你可以通过官方构建脚本生成:
- 运行TensorFlow源码中
tensorflow/contrib/android/build_all.sh脚本,它会自动编译生成包含全算子的tensorflow_inference.so(默认输出路径在tensorflow/contrib/android/libs/${ANDROID_ABI}) - 在你的CMake脚本中引入这个动态库:
add_library(lib_tf SHARED IMPORTED) set_target_properties(lib_tf PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libtensorflow_inference.so)
- 同时确保你的
include_directories包含TensorFlow的头文件目录(比如tensorflow/contrib/android/include)
2. 自行编译动态库
如果需要自定义算子或编译参数,可以修改TensorFlow的构建配置,生成动态库:
- 调整
build_android_all.sh中的构建参数,指定输出动态库而不是静态库 - 编译完成后,将生成的
libtensorflow_inference.so和对应的头文件复制到你的项目中,再按照上面的CMake配置引入即可。
最后,不管用哪种方案,重新构建项目后,加载冻结模型时应该就不会再出现未知算子的错误了。
内容的提问来源于stack exchange,提问作者uelordi
相关产品推荐
相关产品推荐

