面向鲲鹏处理器的tensorflow2.2.0迁移编译与部署
发表于 2025/12/05
0
1 背景
在部分行业场景中,客户侧仍依赖旧版本的 TensorFlow(如 TensorFlow 2.2.0)来支持既有的应用框架与模型开发流程。然而,这些旧版本并未对 ARM 架构提供原生支持,尤其是在面向鲲鹏处理器(Kunpeng)的部署中,直接安装往往会遇到依赖不兼容、环境配置复杂等问题。同时,随着业务需求的演进,客户希望在保持原有模型链路不变的前提下,实现对 ARM 平台的迁移,并对关键组件进行向量化与性能优化,因此需要对老版本 TensorFlow 进行重新编译、适配和端到端部署验证。
基于上述需求,我们整理并总结了一套面向鲲鹏处理器的 TensorFlow 2.2.0 编译与部署流程,涵盖环境搭建、依赖准备、源码编译、向量化优化以及最终的运行验证,可为后续迁移工作提供参考和指导。
2 安装部署流程
1. 容器创建
创建docker配置文件,保存为docker-tf-update-neon.yml:
version: '3.3'
services:
tensorflow-docker:
image: ubuntu:18.04
container_name: tensorflow-docker
restart: unless-stopped
# 数据挂载
volumes:
- /home/user/tensorflow:/workspace/tensorflow:rw
- /home/user/tensorflow:/data:rw
- ./logs:/workspace/logs:rw
- ./config:/workspace/config:rw
dns:
- 8.8.8.8 # Google Public DNS
- 8.8.4.4 # Google Public DNS
cap_add:
- SYS_ADMIN
- SYS_NICE
- NET_ADMIN
# 环境变量
environment:
- DEBIAN_FRONTEND=noninteractive
- TZ=Asia/Shanghai
working_dir: /workspace
network_mode: host
# 无资源限制 - 可使用主机全部CPU、内存、硬盘
# 注释掉或删除任何deploy/resources配置以获得无限制访问
# 启动命令
command: >
bash -c "
hostname tensorflow-docker &&
# 创建目录
mkdir -p /workspace/{logs,config} &&
# 保持运行
while true; do sleep 30; done
"执行docker
docker-compose -f ./docker-tf-update-neon.yml up -d解释:
- volumes → 磁盘目录挂载(跟宿主机文件共享)。
- cap_add → 赋予必要权限。
- environment → 设置容器内环境变量(如免交互安装、时区等)。
- working_dir → 指定容器启动后的工作目录。
- network_mode: host → 与宿主机共享网络(等价于 --network=host)。
- command → 覆盖默认启动命令,可在容器启动时执行自定义脚本或保持容器常驻运行。
2. 在容器里补全 apt 源配置
echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99force-ipv4
cat >/etc/apt/sources.list <<EOF
deb https://ports.ubuntu.com/ubuntu-ports bionic main restricted universe multiverse
deb https://ports.ubuntu.com/ubuntu-ports bionic-updates main restricted universe multiverse
deb https://ports.ubuntu.com/ubuntu-ports bionic-backports main restricted universe multiverse
deb https://ports.ubuntu.com/ubuntu-ports bionic-security main restricted universe multiverseEOF apt-get -o Acquire::Retries=5 update(因为默认 ubuntu:18.04 镜像里可能没有合适的源,可使用华为内部的镜像源加速应用下载)
华为内部源 https://3ms.huawei.com/km/groups/2757573/blogs/details/21413179 3. 手动安装依赖
apt-get install -y --no-install-recommends \
build-essential \
curl \
git \
python3 python3-pip python3-dev \
openjdk-8-jdk \
unzip zip \
zlib1g-dev \
swig virtualenv4. 安装 Python 包
pip3 install --upgrade pip setuptools
pip3 install numpy scipy pandas scikit-learn matplotlib h5py Pillow keras_preprocessing- 下载缓慢,同理可使用华为内部PIP源
https://3ms.huawei.com/km/blogs/details/21564858- 常见问题
Q: Xlocale.h not found on Linux
A: ln -s /usr/include/locale.h /usr/include/xlocale.h
Q: error: Unable to load dependency HDF5, make sure HDF5 is installed properly
A: sudo apt install python3-h5py
Q: Could not find the freetype library.
A: sudo apt-get install libfreetype6 libfreetype6-dev
还是不行,直接sudo apt-get install python-matplotlib5. 确认 Python 3.6 环境
- 检查 Python 版本:
python3 --version 验证容器中的 Python3 是否为 3.6.x(Ubuntu 18.04 默认自带的是 Python 3.6)[tensorflow.org](https://www.tensorflow.org/install/source#install_python_and_the_tensorflow_package_dependencies#:~:text=sudo apt install python3)。输出应类似于 Python 3.6.9。确保使用 Python 3.6 有助于匹配 TensorFlow 2.2.0 的支持范围(TensorFlow 2.2 支持 Python 3.5–3.8)并使用与之兼容的依赖库版本。
- 确保 PIP 版本兼容:
pip3 --version (可选)- 检查 PIP 已升级到最新版本(>= 19.x)以支持安装 TensorFlow 大型 wheel 文件[tensorflow.org](https://www.tensorflow.org/install/source#install_python_and_the_tensorflow_package_dependencies#:~:text=pip install )。这一步通常通过之前的升级命令已完成。
- 检查 Python 版本:python3 --version 验证容器中的 Python3 是否为 3.6.x(Ubuntu 18.04 默认自带的是 Python 3.6)[tensorflow.org]
6. 安装构建依赖(APT 和 PIP)
- 更新 APT 包索引:
sudo apt-get update 更新软件源列表,以确保能够获取最新版本的软件包。这样可以安装最新的编译工具和库。
- 安装系统依赖包:
sudo apt-get install -y --no-install-recommends build-essential openjdk-8-jdk python3-dev python3-pip git wget curl swig 安装编译 TensorFlow 所需的一系列开发工具和库。其中,
build-essential 提供基本的编译工具链,
openjdk-8-jdk 提供 Java 环境用于运行 Bazel,
python3-dev 安装 Python3.6 的开发头文件,
python3-pip 安装 Python 包管理器 PIP,
git 用于获取源码,
wget/curl 用于下载文件,
swig 则是构建过程中需要的接口生成工具。
使用 --no-install-recommends 可以避免安装额外的推荐包。
- 升级 PIP 和 setuptools:
python3 -m pip install --upgrade pip setuptools 使用 Python3 自带的 PIP,将 PIP 本身和 setuptools 工具升级到较新版本。这确保 PIP 版本>=19,以便支持安装 TensorFlow 2.x 的大型 wheel 文件。同时升级 setuptools 可以避免构建过程中潜在的兼容问题。
- 安装所需的 Python 包依赖:
pip3 install numpy six wheel future grpcio 安装 TensorFlow 源码构建和打包过程中需要的 Python 库。
其中包含数值计算库 NumPy、兼容Python2/3的工具包 six、打包所需的 wheel 模块,以及 future 和 grpcio 等库。这些依赖满足了 TensorFlow 2.2.0 构建脚本的要求,例如 numpy>=1.16.0,<2.0、wheel>=0.26 等(Python3 环境下无需安装 futures 包)。安装 grpcio 可以避免构建分发时因缺少该依赖而报错。
7. 安装 Bazel 2.0.0(适配 ARM64)
- 安装 Bazel 构建依赖:
apt-get updateapt-get install -y build-essential openjdk-8-jdk python3 zip unzip wget curl git提供 gcc、JDK8、python、打包工具。
- 下载 Bazel 2.0.0 源码:
wget https://github.com/bazelbuild/bazel/releases/download/2.0.0/bazel-2.0.0-dist.zip官方发布会有 -dist.zip 源码包。
- 解压:
unzip bazel-2.0.0-dist.zip -d bazel-2.0.0-distcd bazel-2.0.0-dist- 构建:
EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk" bash compile.sh这个脚本会在当前目录下用本机工具链编出一个 output/bazel。
- 安装到系统路径:
cp output/bazel /usr/local/bin/8. 下载并检出 TensorFlow v2.2.0 源码
- 克隆 TensorFlow 源码仓库:
git clone https://github.com/tensorflow/tensorflow.git 使用 Git 将 TensorFlow 官方仓库源码克隆到本地。默认会克隆最新的主分支内容。
- 进入源码目录:
cd tensorflow 切换当前工作目录到下载的 TensorFlow 源码目录,为后续构建操作做好准备。
- 检出指定版本标签 v2.2.0:
git checkout v2.2.0 将源码切换到 TensorFlow 2.2.0 发布标签对应的提交。这确保我们使用确切的 v2.2.0 版本代码进行构建。成功后,可以看到 HEAD 切换到了 “v2.2.0”。(注意:也可以在 git clone 时加参数 -b v2.2.0 直接克隆指定版本。)
9. 配置构建选项并运行配置脚本运行配置脚本:
yes "" | ./configure 启动 TensorFlow 提供的交互式配置脚本。
这里使用 yes "" 管道自动对所有提示输入空响应,以采用默认配置值。该脚本会检测系统环境并询问构建选项,例如 Python 可执行路径、Python库路径、是否启用 CUDA(GPU)支持等。
使用空响应相当于选择默认值:脚本将在默认检测到的 Python3 路径(通常是 /usr/bin/python3)上配置构建,CUDA 和其他可选特性默认不启用(CPU-only 架构下 CUDA 默认为 N)。配置完成后,会生成适当的配置文件和环境变量设置(例如确认使用 Python 3.6,禁用 CUDA)。
说明:如果未使用上述自动回答方式,人工交互时请确保选择 Python3 路径(Ubuntu 18.04 下一般输入 /usr/bin/python3,如果脚本默认不是该值)并对是否启用 CUDA、ROCM 等高级特性问题选择 N(不启用)。其他选项如是否优化CPU指令集(默认会启用适合本机的优化)可直接按回车采用默认值。这样配置出来的是针对 ARM64、纯 CPU 环境的构建配置。编译完成后 /tmp/tf_pkg 会有一个 .whl,可以拿到宿主机 pip 安装。
10. 使用 Bazel 编译 TensorFlow 源码(生成 pip 包)
- bazel build前配置:
git config --global http.sslVerify false
export GIT_SSL_NO_VERIFY=1
export JAVA_TOOL_OPTIONS="-Dcom.sun.net.ssl.checkRevocation=false -Dcom.sun.net.ssl.trustStoreType=NONE"
bazel clean --expunge
apt install openjdk-11-jdk -y
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-arm64keytool -importcert -trustcacerts -alias huaweicrt -file Huawei\ Web\ Secure\ Internet\ Gateway\ CA.crt -keystore
$JAVA_HOME/lib/security/cacerts -storepass changeit- 调用 Bazel 编译目标:
bazel build --config=opt --config=noaws --config=monolithic //tensorflow/tools/pip_package:build_pip_package 使用 Bazel 开始编译 TensorFlow。
这里指定了几个配置选项:
--config=opt 启用编译优化(相当于使用最优编译选项进行 Release 构建)。
--config=noaws 禁用 AWS 支持,以避免在 ARM64 环境下编译包含与 AWS 相关的代码时出现不兼容的问题(在 ARM 实例上构建时常用此选项避免引用非 ARM 平台的依赖)。
--config=monolithic 将 TensorFlow 构建为单体静态链接库,避免过多小模块以减少编译过程中可能的内存开销。
这个命令会花费较长时间来编译 TensorFlow 源码并生成用于构建 pip 安装包的二进制目标。根据设备性能,编译过程可能持续数小时。在编译过程中,Bazel 会自动并行利用多核 CPU;如果内存较少(<4GB),可考虑设置环境变量如 --local_ram_resources=<MB> 或限制并行度(例如加入参数 --local_cpu_resources=2)来避免编译因内存不足而中断。
编译成功结束时,生成的目标文件位于 Bazel 的输出目录下。
- 如编译遇到问题:
清缓存再编(避免用到旧头文件产物):
bazel shutdown || truebazel clean --expungerm -rf /root/.cache/bazel重新构建:
bazel build \
--config=opt \
--config=monolithic \
--config=noaws --config=nogcp --config=nohdfs \
//tensorflow/tools/pip_package:build_pip_package11. 打包并验证 TensorFlow 安装包(.whl)
- 安装pip wheel包:
pip3 install wheel- 安装依赖包:
apt-get install liblapack-dev libblas-dev gfortran- 打包生成 .whl 文件:
./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg 运行刚刚编译出的打包脚本,将 TensorFlow 构建产物打包成标准的 pip 安装包(wheel 文件)并输出到指定目录。本命令指定输出路径为 /tmp/tensorflow_pkg,脚本执行后将在该目录下生成一个以 tensorflow-2.2.0 开头的 .whl 文件。
例如,对于 Python 3.6,生成的文件名预计为:tensorflow-2.2.0-cp36-cp36m-linux_aarch64.whl(表示 TensorFlow 2.2.0 适用于 cp36 ABI 的 Linux ARM64)。您可以通过列出该目录内容来确认文件存在,例如运行 ls -l /tmp/tensorflow_pkg 查看文件大小和名称。
- 安装生成的 TensorFlow 包:
sudo pip3 install /tmp/tensorflow_pkg/tensorflow-2.2.0-cp36-cp36m-linux_aarch64.whl 使用 PIP 安装刚生成的 TensorFlow wheel 包(如果在非root环境下,可省略 sudo 或使用虚拟环境)。
这会将构建的 TensorFlow 2.2.0 安装到系统的 Python3 环境中。安装完成后,使用 pip3 list | grep tensorflow 可以看到 tensorflow 2.2.0 已列在已安装包中community.arm.com。
- 验证安装成功:
python3 -c "import tensorflow as tf; print(tf.__version__)" 导入刚安装的 TensorFlow 并打印其版本号,验证安装包可用。正常情况下,此命令应输出 2.2.0,证明我们成功构建并安装了适用于 ARM64 架构的 TensorFlow 2.2.0。
此外也可以尝试运行一个简单的 TensorFlow 运算,例如:python3 -c "import tensorflow as tf; print(tf.reduce_sum(tf.constant([1, 2, 3])).numpy())",若输出计算结果 6 则说明 TensorFlow 能正常运行计算图。
3. 疑难问题:部分难以自动安装的包安装教程
1. Numpy:
回到源码根目录:
cd /workspace备份文件:
cp tensorflow/python/lib/core/bfloat16.cc tensorflow/python/lib/core/bfloat16.cc.bak打补丁(把传给 register_ufunc 的函数指针显式转成 PyUFuncGenericFunction):
sed -i 's/register_ufunc("equal", CompareUFunc/register_ufunc("equal", (PyUFuncGenericFunction)CompareUFunc/' tensorflow/python/lib/core/bfloat16.cc
sed -i 's/register_ufunc("not_equal", CompareUFunc/register_ufunc("not_equal", (PyUFuncGenericFunction)CompareUFunc/' tensorflow/python/lib/core/bfloat16.cc
sed -i 's/register_ufunc("less", CompareUFunc/register_ufunc("less", (PyUFuncGenericFunction)CompareUFunc/' tensorflow/python/lib/core/bfloat16.cc
sed -i 's/register_ufunc("less_equal", CompareUFunc/register_ufunc("less_equal", (PyUFuncGenericFunction)CompareUFunc/' tensorflow/python/lib/core/bfloat16.cc
sed -i 's/register_ufunc("greater", CompareUFunc/register_ufunc("greater", (PyUFuncGenericFunction)CompareUFunc/' tensorflow/python/lib/core/bfloat16.cc
sed -i 's/register_ufunc("greater_equal", CompareUFunc/register_ufunc("greater_equal", (PyUFuncGenericFunction)CompareUFunc/' tensorflow/python/lib/core/bfloat16.cc2. h5py
HDF5 路径在:/usr/lib/aarch64-linux-gnu/hdf5/serial(库) + /usr/include/hdf5/serial(头)
h5py 版本:2.10.0(Python 3.6 友好)
执行下述命令进行手动安装:
apt-get update
apt-get install -y --no-install-recommends libhdf5-serial-dev build-essential python3-dev pkg-config
/usr/local/bin/python -m pip install -U "pip==21.3.1" "setuptools<60" "wheel<0.38"
/usr/local/bin/python -m pip install "Cython==0.29.36" "pkgconfig==1.5.5"export HDF5_DIR=/usr/lib/aarch64-linux-gnu/hdf5/serialexport CFLAGS="-I/usr/include/hdf5/serial" LDFLAGS="-L/usr/lib/aarch64-linux-gnu/hdf5/serial"
/usr/local/bin/python -m pip install --no-cache-dir --no-build-isolation "h5py==2.10.0"
/usr/local/bin/python -c "import h5py; print(h5py.__version__); import h5py.h5 as h5; print('HDF5 lib:', h5.get_libversion())"如果这一步能打印出 2.10.0 和一个 HDF5 版本号(如 1.10.x),说明成功。
3. OpenBLAS
遵照下述指令进行安装:
- 装编译依赖(OpenBLAS + LAPACK + gfortran)
apt-get update
apt-get install -y --no-install-recommends libopenblas-dev liblapack-dev gfortran build-essential python3-dev pkg-config- 让 pip/setuptools 版本对 Py3.6 友好
/usr/local/bin/python -m pip install -U "pip==21.3.1" "setuptools<60" "wheel<0.38"- (可选)显式告诉构建要用 OpenBLAS写个 ~/.numpy-site.cfg,让 SciPy 的构建系统能直接找到库和头:
cat > ~/.numpy-site.cfg <<'EOF'
[openblas]
libraries = openblas
library_dirs = /usr/lib/aarch64-linux-gnu
include_dirs = /usr/include
runtime_library_dirs = /usr/lib/aarch64-linux-gnu
EOF再加上常见环境变量(双保险):
export BLAS=/usr/lib/aarch64-linux-gnu/libopenblas.so
export LAPACK=/usr/lib/aarch64-linux-gnu/libopenblas.so
export NPY_NUM_BUILD_JOBS=$(nproc)(如果仍报“找不到 openblas/lapack”,先确认 libopenblas-dev安装成功,然后再检查:)
python - <<'PY'
import numpy.distutils.system_info as si
print('openblas_info:', si.get_info('openblas_info'))
print('lapack_opt_info:', si.get_info('lapack_opt_info'))PY4. SciPy
- SciPy 1.4.1 源码编译(关键:禁用 build-isolation)
禁用 build-isolation可使其使用当前的 numpy==1.19.5、OpenBLAS 和现成的 Cython完成编译,不会被 PEP517 隔离环境拖去装奇怪的老版本。
/usr/local/bin/python -m pip install --no-cache-dir --no-binary :all: --no-build-isolation "scipy==1.4.1"如果两行都是空 dict,再检查 /usr/lib/aarch64-linux-gnu/ 目录里是否有 libopenblas.so;
有的话大概率是 ~/.numpy-site.cfg 或环境变量没生效——重开一个 shell 或重新 export 后重试。
- 验证 SciPy 安装成功
/usr/local/bin/python - <<'PY'
import scipy, numpy as np
print('scipy', scipy.__version__)
PY应该打印出 scipy 1.4.1。
若报错,在「生成元数据」阶段需要 pybind11:
ModuleNotFoundError: No module named 'pybind11'则进一步按照如下步骤进行安装——先把缺的构建依赖补上,再重新用“无隔离、源码方式”编好 scipy==1.4.1,最后安装 TF wheel。
- 确保编译依赖就绪
apt-get update
apt-get install -y --no-install-recommends libopenblas-dev liblapack-dev gfortran build-essential python3-dev pkg-config
/usr/local/bin/python -m pip install -U "pip==21.3.1" "setuptools<60" "wheel<0.38"- 补齐 SciPy 构建要用到的 Python 依赖
/usr/local/bin/python -m pip install "pybind11==2.6.2" "Cython==0.29.36"pybind11 是 1.4.x 的 scipy.fft/_pocketfft 子包必需;Cython 版本也固定下,避免拉 3.x。
- 给 NumPy/SciPy 指明用 OpenBLAS(双保险)
cat > ~/.numpy-site.cfg <<'EOF'
[openblas]libraries = openblas
library_dirs = /usr/lib/aarch64-linux-gnu
include_dirs = /usr/include
runtime_library_dirs = /usr/lib/aarch64-linux-gnu
EOF
export BLAS=/usr/lib/aarch64-linux-gnu/libopenblas.so
export LAPACK=/usr/lib/aarch64-linux-gnu/libopenblas.so
export NPY_NUM_BUILD_JOBS=$(nproc)
export CC=gcc CXX=g++- 源码安装 SciPy 1.4.1(关键:禁用 build isolation)
/usr/local/bin/python -m pip install --no-cache-dir --no-binary :all: --no-build-isolation "scipy==1.4.1"- 如果机器内存很小、构建中 OOM,可先降并发再试:
export NPY_NUM_BUILD_JOBS=2
/usr/local/bin/python -m pip install --no-cache-dir --no-binary :all: --no-build-isolation "scipy==1.4.1"- 验证 SciPy
/usr/local/bin/python - <<'PY'
import scipy, numpy as np
print('scipy', scipy.__version__)
PY看到 scipy 1.4.1 即为安装成功。


