本文档记录如何将本机 PC 上已经准备好的 Paddle CUDA 12.8 编译环境迁移到无网络的 RTX 5090 服务器,并在 5090 服务器上继续编译 Paddle 源码。

1. 当前前提

本机 PC 已经完成:

  • 已拉取基础镜像:nvidia/cuda:12.8.0-cudnn-devel-ubuntu22.04
  • 已构建 Paddle 编译镜像:paddle-build:cuda12.8-cudnn-devel-ubuntu22.04
  • Dockerfile 已配置国内 apt 源和 pip 源
  • Paddle 源码已拉取到:/home/wanna/tmp/paddle/Paddle
  • Paddle submodule 已初始化
  • 本机 CMake 配置已成功
  • CUDA 12.8 已验证支持 RTX 5090 架构:sm_120

5090 服务器信息:

SSH: wml@172.30.38.34
密码: wml
GPU: NVIDIA GeForce RTX 5090
Driver: 570.133.07
CUDA Runtime: 12.8

2. 需要迁移的内容

需要从本机传到 5090 服务器:

1. paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 镜像 tar 包
2. /home/wanna/tmp/paddle/Paddle 源码目录
3. /home/wanna/tmp/paddle/cache 缓存目录
4. /home/wanna/tmp/paddle/ccache 缓存目录,可选

建议连同 Paddle/build 一起传输,因为本机 CMake 已经成功,build 中包含已下载和已配置的部分 third_party 内容。

3. 本机检查 submodule 完整性

在本机执行:

cd /home/wanna/tmp/paddle/Paddle

git config --global --add safe.directory "*"

git submodule sync --recursive
git submodule update --init --recursive --force --checkout --jobs 8

检查 submodule 是否完整:

git submodule status --recursive | grep '^-' && echo "submodule missing" || echo "submodule ok"

检查曾经出错的 gloo:

ls -lh third_party/gloo/CMakeLists.txt

如果能看到 CMakeLists.txt,说明 third_party/gloo 已恢复正常。

4. 本机保存 Docker 镜像

在本机执行:

cd /home/wanna/tmp/paddle

docker save paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 \
  -o paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

建议使用 zstd 压缩:

zstd -T0 paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

生成文件:

paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst

5. 本机打包 Paddle 源码和 build 目录

在本机执行:

cd /home/wanna/tmp/paddle

tar --numeric-owner -I 'zstd -T0' -cf Paddle-source-with-build.tar.zst Paddle

该包包含:

Paddle 源码
Paddle/.git
Paddle/third_party submodule
Paddle/build CMake 配置和 third_party 构建缓存

说明:

  • --numeric-owner 用于避免本机和服务器用户名、UID 不一致导致解压归属异常。
  • 保留 .git 是为了避免 Paddle 编译脚本读取版本信息失败。
  • 保留 build 是为了减少 5090 无网环境下重新下载 third_party 的概率。

6. 本机打包 cache 和 ccache

打包 cache:

cd /home/wanna/tmp/paddle

tar --numeric-owner -I 'zstd -T0' -cf paddle-cache.tar.zst cache

打包 ccache,可选:

tar --numeric-owner -I 'zstd -T0' -cf paddle-ccache.tar.zst ccache

如果 ccache 非常大,可以不传。它只影响二次编译速度,不影响能否编译。

7. 传输文件到 5090 服务器

在本机执行:

cd /home/wanna/tmp/paddle

rsync -avP paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst \
  wml@172.30.38.34:/home/wml/

rsync -avP Paddle-source-with-build.tar.zst \
  wml@172.30.38.34:/home/wml/

rsync -avP paddle-cache.tar.zst \
  wml@172.30.38.34:/home/wml/

rsync -avP paddle-ccache.tar.zst \
  wml@172.30.38.34:/home/wml/

如果不传 ccache,跳过最后一条命令。

8. 5090 服务器导入 Docker 镜像

登录 5090 服务器:

ssh wml@172.30.38.34

进入目录:

cd /home/wml

解压镜像包:

zstd -d paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst

导入镜像:

docker load -i paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

确认镜像存在:

docker images | grep paddle-build

9. 5090 服务器解压源码和缓存

在 5090 服务器执行:

cd /home/wml

tar -I zstd -xf Paddle-source-with-build.tar.zst
tar -I zstd -xf paddle-cache.tar.zst

如果传输了 ccache:

tar -I zstd -xf paddle-ccache.tar.zst

解压后目录建议为:

/home/wml/
  Paddle/
  cache/
  ccache/
  paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

如果没有传 ccache,创建空目录:

mkdir -p /home/wml/ccache

10. 5090 服务器启动编译容器

在 5090 服务器执行:

docker run -it --name paddle-cu128-build-5090 \
  --gpus all \
  --shm-size=64g \
  --network=none \
  -v /home/wml/Paddle:/workspace/Paddle \
  -v /home/wml/cache:/root/.cache \
  -v /home/wml/ccache:/root/.ccache \
  -w /workspace/Paddle \
  paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 \
  bash
docker run -it --name paddle-cu128-build-5090 \
  --gpus all \
  --shm-size=64g \
  --network=none \
  -v /home/wanna/Paddle:/workspace/Paddle \
  -v /home/wanna/cache:/root/.cache \
  -v /home/wanna/ccache:/root/.ccache \
  -w /workspace/Paddle \
  paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 \
  bash

参数说明:

  • --gpus all:允许容器使用全部 5090 GPU。
  • --shm-size=64g:增大共享内存,降低构建和测试时的内存问题。
  • --network=none:明确容器在离线环境下运行。
  • /home/wml/Paddle:/workspace/Paddle:挂载 Paddle 源码。
  • /home/wml/cache:/root/.cache:挂载 pip/CMake 等缓存。
  • /home/wml/ccache:/root/.ccache:挂载 ccache 缓存。

11. 容器内检查环境

进入容器后执行:

git config --global --add safe.directory "*"

检查 GPU 和 CUDA:

nvidia-smi
nvcc --version
nvcc --list-gpu-arch | grep compute_120

检查 Paddle 源码和 submodule:

cd /workspace/Paddle

ls -lh third_party/gloo/CMakeLists.txt

git submodule status --recursive | grep '^-' && echo "submodule missing" || echo "submodule ok"

12. 推荐在 5090 上重新 CMake

由于本机和 5090 服务器路径、GPU、容器 ID 可能不同,建议在 5090 上重新执行 CMake。

为了尽量保留已下载的 third_party,不要直接删除整个 build,可以只删除 CMake 缓存:

cd /workspace/Paddle/build

rm -f CMakeCache.txt
rm -rf CMakeFiles

重新配置:

cmake .. \
  -GNinja \
  -DPYTHON_EXECUTABLE=$(which python) \
  -DWITH_GPU=ON \
  -DWITH_TESTING=OFF \
  -DWITH_DISTRIBUTE=ON \
  -DWITH_MKL=ON \
  -DWITH_ONEDNN=ON \
  -DWITH_PYTHON=ON \
  -DCMAKE_BUILD_TYPE=Release \
  -DPY_VERSION=3.10 \
  -DWITH_CINN=ON \
  -DCUDA_ARCH_NAME=Manual \
  -DCUDA_ARCH_BIN="12.0" \
  -DWITH_XPU=OFF \
  -DWITH_ROCM=OFF

确认 CMake 日志中包含:

-- CUDA detected: 12.8
-gencode arch=compute_120,code=sm_120
-- Configuring done
-- Generating done

13. 在 5090 上正式编译

进入 build 目录:

cd /workspace/Paddle/build

推荐先使用较保守的并发:

ninja paddle_python -j16

如果内存、磁盘和负载都稳定,可以提高并发:

ninja paddle_python -j32

如果出现 OOM 或系统负载过高,降低并发:

ninja paddle_python -j8

编译完成后查看 wheel:

ls -lh /workspace/Paddle/build/python/dist/

如果 ninja paddle_python 已经执行结束,但 build/python/dist 目录不存在或没有 .whl 文件,可以手动执行 Python wheel 打包:

cd /workspace/Paddle/build/python
python setup.py bdist_wheel

然后重新查找 wheel:

find /workspace/Paddle/build -type f -name "*.whl" -print

常见输出目录为:

/workspace/Paddle/build/python/dist/

14. 安装并验证 Paddle

在 5090 容器内安装 wheel:

pip install /workspace/Paddle/build/python/dist/*.whl

如果服务器或容器无网络,pip 可能会尝试访问 PyPI 下载 CUDA Python 依赖,例如 nvidia-cuda-nvrtc-cu12==12.8.61。由于当前 Docker 镜像已经提供 CUDA 12.8 运行库,建议离线安装时跳过依赖解析:

pip install --no-index --no-deps --force-reinstall \
  /workspace/Paddle/build/python/dist/paddlepaddle_gpu-*.whl

运行验证脚本:

python - <<'PY'
import paddle

print("Paddle version:", paddle.__version__)
print("CUDA compiled:", paddle.is_compiled_with_cuda())
print("Device before:", paddle.device.get_device())

paddle.set_device("gpu:0")
x = paddle.randn([1024, 1024], dtype="float32")
y = paddle.matmul(x, x)

print("Device after:", paddle.device.get_device())
print(y.shape)
print("OK")
PY

如果输出包含以下内容,说明编译出的 Paddle wheel 可以在 5090 上使用:

CUDA compiled: True
GPU Compute Capability: 12.0
Driver API Version: 12.8
Runtime API Version: 12.8
Device after: gpu:0
OK

15. 最短命令汇总

15.1 本机 PC

cd /home/wanna/tmp/paddle

docker save paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 \
  -o paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

zstd -T0 paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

tar --numeric-owner -I 'zstd -T0' -cf Paddle-source-with-build.tar.zst Paddle
tar --numeric-owner -I 'zstd -T0' -cf paddle-cache.tar.zst cache
tar --numeric-owner -I 'zstd -T0' -cf paddle-ccache.tar.zst ccache

rsync -avP paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst wml@172.30.38.34:/home/wml/
rsync -avP Paddle-source-with-build.tar.zst wml@172.30.38.34:/home/wml/
rsync -avP paddle-cache.tar.zst wml@172.30.38.34:/home/wml/
rsync -avP paddle-ccache.tar.zst wml@172.30.38.34:/home/wml/

15.2 5090 服务器

cd /home/wml

zstd -d paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst
docker load -i paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

tar -I zstd -xf Paddle-source-with-build.tar.zst
tar -I zstd -xf paddle-cache.tar.zst
tar -I zstd -xf paddle-ccache.tar.zst

docker run -it --name paddle-cu128-build-5090 \
  --gpus all \
  --shm-size=64g \
  --network=none \
  -v /home/wml/Paddle:/workspace/Paddle \
  -v /home/wml/cache:/root/.cache \
  -v /home/wml/ccache:/root/.ccache \
  -w /workspace/Paddle \
  paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 \
  bash

15.3 容器内

git config --global --add safe.directory "*"

cd /workspace/Paddle/build

rm -f CMakeCache.txt
rm -rf CMakeFiles

cmake .. \
  -GNinja \
  -DPYTHON_EXECUTABLE=$(which python) \
  -DWITH_GPU=ON \
  -DWITH_TESTING=OFF \
  -DWITH_DISTRIBUTE=ON \
  -DWITH_MKL=ON \
  -DWITH_ONEDNN=ON \
  -DWITH_PYTHON=ON \
  -DCMAKE_BUILD_TYPE=Release \
  -DPY_VERSION=3.10 \
  -DWITH_CINN=ON \
  -DCUDA_ARCH_NAME=Manual \
  -DCUDA_ARCH_BIN="12.0" \
  -DWITH_XPU=OFF \
  -DWITH_ROCM=OFF

ninja paddle_python -j16

16. 常见问题

16.1 Git 报 dubious ownership

报错示例:

fatal: detected dubious ownership in repository at '/workspace/Paddle'

处理:

git config --global --add safe.directory "*"

16.2 gloo 缺少 CMakeLists.txt

报错示例:

The source directory "/workspace/Paddle/third_party/gloo" does not appear to contain CMakeLists.txt.

说明 third_party/gloo submodule 不完整。在本机重新修复并打包:

cd /home/wanna/tmp/paddle/Paddle

git submodule sync --recursive
git submodule update --init --recursive --force --checkout --jobs 8 third_party/gloo

ls -lh third_party/gloo/CMakeLists.txt

16.3 5090 无网导致 third_party 下载失败

处理建议:

  • 确认本机 CMake 已经成功跑过。
  • 打包时包含 Paddle/build。
  • 打包并挂载 /root/.cache 对应的 cache 目录。
  • 如果仍失败,需要回本机补齐对应 third_party 文件后重新打包。

16.4 编译中 OOM

降低 Ninja 并发:

ninja paddle_python -j8

16.5 磁盘空间不足

5090 服务器建议至少保留 100 GB 可用空间,最好 150 GB 到 200 GB。检查命令:

df -h

16.6 链接阶段找不到 libssl 或 libcrypto

报错示例:

/usr/bin/ld: cannot find -lssl: No such file or directory
/usr/bin/ld: cannot find -lcrypto: No such file or directory

原因:容器中有 OpenSSL 运行库,例如 libssl.so.3 和 libcrypto.so.3,但缺少开发包通常提供的无版本软链接 libssl.so 和 libcrypto.so。

如果 5090 容器离线,不能通过 apt 安装 libssl-dev,可以先检查:

ls -lh /usr/lib/x86_64-linux-gnu/libssl.so*
ls -lh /usr/lib/x86_64-linux-gnu/libcrypto.so*

如果存在:

/usr/lib/x86_64-linux-gnu/libssl.so.3
/usr/lib/x86_64-linux-gnu/libcrypto.so.3

则可以临时创建软链接继续编译:

ln -sf /usr/lib/x86_64-linux-gnu/libssl.so.3 /usr/lib/x86_64-linux-gnu/libssl.so
ln -sf /usr/lib/x86_64-linux-gnu/libcrypto.so.3 /usr/lib/x86_64-linux-gnu/libcrypto.so
ldconfig

cd /workspace/Paddle/build
ninja paddle_python -j8

永久修复方式是在本机 Dockerfile 中加入:

libssl-dev
openssl

然后重新构建镜像、保存并传输到 5090。

16.7 编译完成但没有生成 whl

现象:ninja paddle_python 执行结束后,在 build 目录没有直接看到 Python 安装包。

先查找 wheel:

cd /workspace/Paddle/build
find . -type f -name "*.whl" -print

常见位置:

/workspace/Paddle/build/python/dist/*.whl
/workspace/Paddle/build/dist/*.whl

如果没有找到,可以进入 Python 打包目录手动打包:

cd /workspace/Paddle/build/python
python setup.py bdist_wheel

如果报错:

RuntimeError: Missing build dependency: httpx
Please run 'pip install -r python/requirements.txt' to make sure you have all the dependencies installed.

说明缺少 Python 打包依赖。若容器有网络,可以直接安装:

python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple httpx

cd /workspace/Paddle/build/python
python setup.py bdist_wheel

如果 5090 容器无网络,需要在有网络的本机 PC 下载离线 wheel 包。

本机 PC 执行:

mkdir -p /home/wanna/tmp/paddle/pip_wheels

docker run --rm \
  -v /home/wanna/tmp/paddle/pip_wheels:/wheels \
  paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 \
  bash -lc '
python -m pip download -i https://pypi.tuna.tsinghua.edu.cn/simple \
  -d /wheels \
  httpx
'

传到 5090:

rsync -avP /home/wanna/tmp/paddle/pip_wheels/ \
  wml@172.30.38.34:/home/wml/pip_wheels/

如果容器启动时没有挂载该目录,在 5090 宿主机复制到容器:

docker cp /home/wml/pip_wheels paddle-cu128-build-5090:/tmp/pip_wheels

容器内离线安装:

python -m pip install --no-index --find-links=/tmp/pip_wheels httpx

cd /workspace/Paddle/build/python
python setup.py bdist_wheel

find /workspace/Paddle/build -type f -name "*.whl" -print

更完整的做法是在本机提前下载 python/requirements.txt 的所有依赖:

mkdir -p /home/wanna/tmp/paddle/pip_wheels

docker run --rm \
  -v /home/wanna/tmp/paddle/Paddle:/workspace/Paddle \
  -v /home/wanna/tmp/paddle/pip_wheels:/wheels \
  paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 \
  bash -lc '
cd /workspace/Paddle
python -m pip download -i https://pypi.tuna.tsinghua.edu.cn/simple \
  -d /wheels \
  -r python/requirements.txt
'

传输后在 5090 容器内离线安装:

python -m pip install --no-index --find-links=/tmp/pip_wheels \
  -r /workspace/Paddle/python/requirements.txt

更多推荐