踩坑 5090 编译构建 Paddle 源码

踩坑 5090 编译构建 Paddle 源码

本文记录一次在 RTX 5090 服务器上离线编译 Paddle 源码的完整过程,包括从 CUDA 12.8 Docker 编译镜像构建、本机准备 Paddle 源码和依赖、迁移到无网络 5090 服务器、CMake 配置、Ninja 编译、wheel 打包,到最终验证的全流程。

文档中涉及的路径、服务器地址、用户名等信息均已脱敏,实际执行时请替换为自己的环境。

1. 背景

目标是在一台无网络的 RTX 5090 服务器上编译 Paddle 源码,产出支持 5090 的 Paddle Python wheel 包。

服务器环境大致如下:

text 复制代码
GPU: NVIDIA GeForce RTX 5090 x 4
Driver: 570.x
Host CUDA Runtime: 12.8
Network: 离线,无外网
Docker: 已安装
NVIDIA Container Toolkit: 已安装

本机 PC 环境:

text 复制代码
Network: 有外网
Docker: 已安装
Workspace: <LOCAL_WORKSPACE>/paddle
Paddle source: <LOCAL_WORKSPACE>/paddle/Paddle

5090 服务器环境:

text 复制代码
SSH: <USER>@<SERVER_IP>
Workspace: <REMOTE_WORKSPACE>
Paddle source: <REMOTE_WORKSPACE>/Paddle

2. 为什么不能直接用 CUDA 12.6 镜像

一开始服务器上已有一个 paddle:cu126 镜像,看起来像是 Paddle 的 CUDA 12.6 环境。但实际检查后发现它不适合 RTX 5090。

进入容器检查:

bash 复制代码
docker run --rm -it --gpus all paddle:cu126 bash

容器内执行:

bash 复制代码
nvcc --version
nvcc --list-gpu-arch

结果显示 CUDA 12.6 的 nvcc 只支持到:

text 复制代码
compute_90

没有:

text 复制代码
compute_120
sm_120

再测试:

bash 复制代码
cat >/tmp/arch.cu <<'CU'
#include <stdio.h>
__global__ void k(){}
int main(){k<<<1,1>>>(); cudaDeviceSynchronize(); printf("ok\n"); return 0;}
CU

nvcc -arch=sm_120 /tmp/arch.cu -o /tmp/arch_sm120.out

报错:

text 复制代码
nvcc fatal: Value 'sm_120' is not defined for option 'gpu-architecture'

镜像里已有的 Paddle wheel 也无法在 5090 上运行,报错类似:

text 复制代码
Mismatched GPU Architecture:
The installed PaddlePaddle package was compiled for 61 70 75 80 86 89 90,
but your current GPU is 120

FatalError: Unsupported GPU architecture

结论:RTX 5090 需要 CUDA 12.8 或更高版本的编译工具链,CUDA 12.6 不适合作为最终编译环境。

3. 构建 CUDA 12.8 Paddle 编译镜像

本机 PC 先拉取 CUDA 12.8 devel 镜像:

bash 复制代码
docker pull nvidia/cuda:12.8.0-cudnn-devel-ubuntu22.04

如果拉取较慢,可以配置 Docker 镜像加速或使用 NVIDIA NGC 源。拉取成功后,以它为基础构建 Paddle 编译镜像。

3.1 Dockerfile

在本机创建目录:

bash 复制代码
mkdir -p <LOCAL_WORKSPACE>/paddle
cd <LOCAL_WORKSPACE>/paddle

创建 Dockerfile

dockerfile 复制代码
FROM nvidia/cuda:12.8.0-cudnn-devel-ubuntu22.04

ARG DEBIAN_FRONTEND=noninteractive
ARG APT_MIRROR=mirrors.aliyun.com
ARG PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
ARG PIP_TRUSTED_HOST=pypi.tuna.tsinghua.edu.cn

ENV TZ=Asia/Shanghai \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8 \
    PYTHONUNBUFFERED=1 \
    PIP_INDEX_URL=${PIP_INDEX_URL} \
    PIP_TRUSTED_HOST=${PIP_TRUSTED_HOST} \
    PIP_NO_CACHE_DIR=1 \
    CUDA_HOME=/usr/local/cuda \
    PATH=/usr/local/cuda/bin:${PATH} \
    LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH}

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

RUN set -eux; \
    cp /etc/apt/sources.list /etc/apt/sources.list.bak; \
    sed -i "s@http://archive.ubuntu.com/ubuntu/@http://${APT_MIRROR}/ubuntu/@g" /etc/apt/sources.list; \
    sed -i "s@http://security.ubuntu.com/ubuntu/@http://${APT_MIRROR}/ubuntu/@g" /etc/apt/sources.list; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
      build-essential \
      gcc \
      g++ \
      make \
      ninja-build \
      cmake \
      git \
      wget \
      curl \
      ca-certificates \
      pkg-config \
      libssl-dev \
      openssl \
      patchelf \
      ccache \
      swig \
      unzip \
      tar \
      gzip \
      zstd \
      file \
      sudo \
      vim \
      less \
      openssh-client \
      python3 \
      python3-dev \
      python3-pip \
      python3-venv \
      python-is-python3; \
    rm -rf /var/lib/apt/lists/*

RUN set -eux; \
    python -m pip config set global.index-url "${PIP_INDEX_URL}"; \
    python -m pip config set global.trusted-host "${PIP_TRUSTED_HOST}"; \
    python -m pip install --upgrade pip setuptools wheel; \
    python -m pip install \
      numpy \
      Cython \
      pybind11 \
      protobuf \
      requests \
      six \
      decorator \
      typing_extensions \
      packaging \
      pyyaml \
      certifi \
      urllib3 \
      opt_einsum==3.3.0 \
      networkx \
      httpx \
      Pillow \
      safetensors \
      astor \
      gast \
      cloudpickle \
      psutil \
      jinja2 \
      pybind11_stubgen

RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends libnccl2 libnccl-dev || true; \
    rm -rf /var/lib/apt/lists/*

RUN set -eux; \
    mkdir -p /workspace /root/.cache /root/.ccache; \
    ccache --set-config=max_size=20G || true

WORKDIR /workspace

CMD ["/bin/bash"]

这里踩过的坑主要有三个:

  • jinja2 会导致 CINN 相关代码生成失败。
  • httpx 会导致 python setup.py bdist_wheel 打包失败。
  • libssl-dev 会导致链接阶段找不到 -lssl-lcrypto

3.2 构建镜像

使用清华 apt 源构建:

bash 复制代码
cd <LOCAL_WORKSPACE>/paddle

docker build \
  --build-arg APT_MIRROR=mirrors.tuna.tsinghua.edu.cn \
  -t paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 .

3.3 验证镜像工具链

bash 复制代码
docker run --rm -it paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 bash -lc '
nvcc --version
gcc --version | head -1
g++ --version | head -1
cmake --version | head -1
ninja --version
python --version
pip --version
git --version
patchelf --version
swig -version | head -2
ccache --version | head -1
'

3.4 验证 sm_120 编译支持

bash 复制代码
docker run --rm -it paddle-build:cuda12.8-cudnn-devel-ubuntu22.04 bash -lc '
set -e
cat >/tmp/arch.cu << "CU"
#include <stdio.h>
__global__ void k(){}
int main(){k<<<1,1>>>(); cudaDeviceSynchronize(); printf("ok\n"); return 0;}
CU

nvcc -arch=sm_120 /tmp/arch.cu -o /tmp/arch_sm120.out
echo "compile sm_120 ok"
'

只要能看到:

text 复制代码
compile sm_120 ok

说明镜像里的 CUDA 12.8 编译器支持 RTX 5090 架构。

4. 拉取 Paddle 源码和 submodule

本机 PC 执行:

bash 复制代码
cd <LOCAL_WORKSPACE>/paddle

git clone https://github.com/PaddlePaddle/Paddle.git
cd Paddle

选择分支,例如:

bash 复制代码
git checkout develop

初始化 submodule:

bash 复制代码
git submodule sync --recursive
git submodule update --init --recursive --jobs 8

检查:

bash 复制代码
git submodule status --recursive | grep '^-' && echo "submodule missing" || echo "submodule ok"

如果输出:

text 复制代码
submodule ok

说明 submodule 完整。

5. 进入本机 Paddle 编译容器

创建进入容器脚本,例如 paddle.sh

bash 复制代码
#!/usr/bin/env bash
set -euo pipefail

IMAGE="${IMAGE:-paddle-build:cuda12.8-cudnn-devel-ubuntu22.04}"
PADDLE_DIR="${PADDLE_DIR:-<LOCAL_WORKSPACE>/paddle/Paddle}"
CACHE_DIR="${CACHE_DIR:-<LOCAL_WORKSPACE>/paddle/cache}"
CCACHE_DIR="${CCACHE_DIR:-<LOCAL_WORKSPACE>/paddle/ccache}"
CONTAINER_NAME="${CONTAINER_NAME:-paddle-cu128-build}"

if [ ! -d "${PADDLE_DIR}" ]; then
  echo "Paddle source directory not found: ${PADDLE_DIR}" >&2
  exit 1
fi

mkdir -p "${CACHE_DIR}" "${CCACHE_DIR}"

if docker ps --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
  exec docker exec -it "${CONTAINER_NAME}" bash
fi

if docker ps -a --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
  docker rm "${CONTAINER_NAME}" >/dev/null
fi

GPU_ARGS=()
if command -v nvidia-smi >/dev/null 2>&1; then
  GPU_ARGS=(--gpus all)
fi

exec docker run -it \
  --name "${CONTAINER_NAME}" \
  "${GPU_ARGS[@]}" \
  --shm-size=64g \
  -v "${PADDLE_DIR}:/workspace/Paddle" \
  -v "${CACHE_DIR}:/root/.cache" \
  -v "${CCACHE_DIR}:/root/.ccache" \
  -w /workspace/Paddle \
  "${IMAGE}" \
  bash -lc 'git config --global --add safe.directory "*"; exec bash'

加执行权限:

bash 复制代码
chmod +x <LOCAL_WORKSPACE>/paddle/paddle.sh

进入容器:

bash 复制代码
cd <LOCAL_WORKSPACE>/paddle
./paddle.sh

6. 本机 CMake 配置

进入容器后:

bash 复制代码
cd /workspace/Paddle
mkdir -p build
cd build

执行 CMake:

bash 复制代码
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

成功时应看到类似:

text 复制代码
-- CUDA detected: 12.8.61
-- NVCC_FLAGS_EXTRA: -gencode arch=compute_120,code=sm_120 -Xfatbin -compress-all
-- Configuring done
-- Generating done

本机不需要是 5090。只要 nvcc 支持 sm_120,就可以生成面向 5090 的编译配置。

7. 本机编译或只准备缓存

如果本机资源足够,可以先编译:

bash 复制代码
cd /workspace/Paddle/build
ninja paddle_python -j8

如果本机不是 5090,也可以编译,因为这里是用 CUDA 12.8 交叉编译 sm_120。但是最终 GPU 运行验证必须在 5090 服务器上完成。

如果本机只是为了给离线服务器准备 third_party 缓存,那么 CMake 成功后也可以直接进入迁移阶段。

8. 迁移到 5090 服务器

8.1 保存 Docker 镜像

本机 PC 执行:

bash 复制代码
cd <LOCAL_WORKSPACE>/paddle

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

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

生成:

text 复制代码
paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst

8.2 打包源码和缓存

bash 复制代码
cd <LOCAL_WORKSPACE>/paddle

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

建议保留:

text 复制代码
Paddle/.git
Paddle/third_party
Paddle/build

因为 5090 服务器无网,保留这些内容能减少 third_party 下载失败的概率。

8.3 传输文件

bash 复制代码
cd <LOCAL_WORKSPACE>/paddle

rsync -avP paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst \
  <USER>@<SERVER_IP>:<REMOTE_WORKSPACE>/

rsync -avP Paddle-source-with-build.tar.zst \
  <USER>@<SERVER_IP>:<REMOTE_WORKSPACE>/

rsync -avP paddle-cache.tar.zst \
  <USER>@<SERVER_IP>:<REMOTE_WORKSPACE>/

rsync -avP paddle-ccache.tar.zst \
  <USER>@<SERVER_IP>:<REMOTE_WORKSPACE>/

如果传输大文件不稳定,可以使用 rsync -avP --partial --inplace

9. 5090 服务器解压和导入

登录服务器:

bash 复制代码
ssh <USER>@<SERVER_IP>

进入工作目录:

bash 复制代码
cd <REMOTE_WORKSPACE>

导入镜像:

bash 复制代码
zstd -d -f paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst
docker load -i paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar

解压源码和缓存:

bash 复制代码
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

如果遇到:

text 复制代码
time stamp ... is ... in the future

通常是本机和服务器时间不一致导致的警告,可以先忽略。

但如果遇到:

text 复制代码
Unexpected EOF in archive
premature end

说明压缩包损坏或传输不完整,需要重新传输,并建议校验:

bash 复制代码
zstd -t Paddle-source-with-build.tar.zst
sha256sum Paddle-source-with-build.tar.zst

10. 5090 启动编译容器

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

容器内:

bash 复制代码
git config --global --add safe.directory "*"

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

11. 5090 重新 CMake

建议在 5090 上重新配置 CMake,但尽量保留 build/third_party 缓存:

bash 复制代码
cd /workspace/Paddle/build
rm -f CMakeCache.txt
rm -rf CMakeFiles

重新配置:

bash 复制代码
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

12. 5090 编译 Paddle

bash 复制代码
cd /workspace/Paddle/build
ninja paddle_python -j8

如果服务器内存和磁盘充足,可以尝试:

bash 复制代码
ninja paddle_python -j16

如果出现 OOM,降低并发:

bash 复制代码
ninja paddle_python -j4

13. 手动打包 wheel

有时 ninja paddle_python 编译结束后,build/python/dist 目录还没有生成 .whl。这时进入 Python 打包目录:

bash 复制代码
cd /workspace/Paddle/build/python
python setup.py bdist_wheel

查找 wheel:

bash 复制代码
find /workspace/Paddle/build -type f -name "*.whl" -print

通常输出目录是:

text 复制代码
/workspace/Paddle/build/python/dist/

如果报缺依赖,例如:

text 复制代码
RuntimeError: Missing build dependency: httpx

安装:

bash 复制代码
python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple httpx

或者更完整地安装 Paddle Python requirements:

bash 复制代码
cd /workspace/Paddle
python -m pip install -r python/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

如果 5090 容器严格无网,应提前在本机下载这些 wheel 包并传入容器。

14. 安装并验证

安装 wheel:

bash 复制代码
pip install /workspace/Paddle/build/python/dist/*.whl

如果 5090 容器无网络,直接安装 wheel 时可能会尝试从 PyPI 拉取 CUDA Python 依赖,例如:

text 复制代码
nvidia-cuda-nvrtc-cu12==12.8.61

报错示例:

text 复制代码
ERROR: Could not find a version that satisfies the requirement nvidia-cuda-nvrtc-cu12==12.8.61
ERROR: No matching distribution found for nvidia-cuda-nvrtc-cu12==12.8.61

由于当前 Docker 镜像本身已经提供 CUDA 12.8、NVRTC、cuDNN 等运行库,安装自编译 wheel 时可以跳过依赖解析:

bash 复制代码
pip install --no-index --no-deps --force-reinstall \
  /workspace/Paddle/build/python/dist/paddlepaddle_gpu-*.whl

如果容器有网络,也可以不加 --no-index,但离线服务器建议固定使用 --no-index --no-deps,避免 pip 访问外网。

验证 GPU:

bash 复制代码
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

成功标志:

text 复制代码
CUDA compiled: True
GPU Compute Capability: 12.0
Driver API Version: 12.8
Runtime API Version: 12.8
Device after: gpu:0
OK

一次实际成功验证输出类似:

text 复制代码
CUDA compiled: True
Device before: gpu:0
Please NOTE: device: 0, GPU Compute Capability: 12.0, Driver API Version: 12.8, Runtime API Version: 12.8
Device after: gpu:0
paddle.Size([1024, 1024])
OK

其中 GPU Compute Capability: 12.0 说明运行目标确实是 RTX 5090 对应的 sm_120 架构,OK 说明基础 GPU 张量计算已经跑通。

15. 踩坑总结

15.1 CUDA 12.6 不支持 5090

CUDA 12.6 的 nvcc 不认识 sm_120,所以不能用来编译 RTX 5090 原生 Paddle wheel。

解决:使用 CUDA 12.8 devel 镜像。

15.2 Git dubious ownership

容器 root 用户访问宿主机 Git 仓库会报:

text 复制代码
fatal: detected dubious ownership in repository

解决:

bash 复制代码
git config --global --add safe.directory "*"

15.3 submodule 不完整

典型错误:

text 复制代码
third_party/gloo does not appear to contain CMakeLists.txt

解决:

bash 复制代码
git submodule sync --recursive
git submodule update --init --recursive --force --checkout --jobs 8

15.4 CINN 代码生成失败

典型错误:

text 复制代码
Cannot find source file: cinn_op.cc
ModuleNotFoundError: No module named 'jinja2'

解决:Dockerfile 安装:

text 复制代码
jinja2
pybind11_stubgen

15.5 链接找不到 OpenSSL

典型错误:

text 复制代码
/usr/bin/ld: cannot find -lssl
/usr/bin/ld: cannot find -lcrypto

解决:Dockerfile 安装:

text 复制代码
libssl-dev
openssl

如果已经在离线容器中,也可以临时软链接:

bash 复制代码
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

15.6 wheel 打包缺 httpx

典型错误:

text 复制代码
RuntimeError: Missing build dependency: httpx

解决:Dockerfile 安装 httpx,或在容器内安装:

bash 复制代码
python -m pip install httpx

15.7 离线安装 wheel 时 pip 拉取 nvidia-cuda-nvrtc-cu12 失败

典型错误:

text 复制代码
ERROR: Could not find a version that satisfies the requirement nvidia-cuda-nvrtc-cu12==12.8.61
ERROR: No matching distribution found for nvidia-cuda-nvrtc-cu12==12.8.61

原因:自编译的 Paddle wheel 声明了 CUDA Python 依赖,但 5090 容器无网络,pip 无法访问 PyPI;同时 CUDA 12.8 运行库已经由 Docker 镜像提供,不需要 pip 再下载。

解决:离线安装时跳过依赖解析:

bash 复制代码
pip install --no-index --no-deps --force-reinstall \
  paddlepaddle_gpu-*.whl

15.8 tar 解压 Unexpected EOF

这是压缩包损坏或传输不完整,不是时间戳问题。

解决:重新传输,并校验:

bash 复制代码
zstd -t Paddle-source-with-build.tar.zst
sha256sum Paddle-source-with-build.tar.zst

16. 最终建议

为了后续可复现,建议保留以下产物:

text 复制代码
paddle-build-cuda12.8-cudnn-devel-ubuntu22.04.tar.zst
Paddle-source-with-build.tar.zst
paddle-cache.tar.zst
paddle-ccache.tar.zst
最终编译出的 paddlepaddle*.whl

如果要重新部署到另一台 5090 服务器,只需要导入镜像、解压源码和缓存,再执行 CMake、Ninja 和 wheel 打包即可。

相关推荐
Canace1 小时前
给 Claude 一个链接,它真的读了原文吗
前端·人工智能·ai编程
星火10241 小时前
【LangChain4j系列01】LangChain4j 快速入门与核心概念
java·人工智能
阿宇的技术日志1 小时前
美团图灵 Agent 评测文章学习:从 “打分“ 到 “基建“,Agent 评测的认知升级
人工智能·agent 评测
武子康1 小时前
GPT-Live 与 GPT-Realtime:产品模型和公开 API 不应混写
人工智能·chatgpt·agent
zhongerzixunshi1 小时前
健全创新激励机制,激活企业发展内生动力
大数据·人工智能
changtianshuiyue1 小时前
拆解 AI Agent 三大核心机制:从概念到 OpenAI API 接口实现
人工智能
beiju1 小时前
从 Demo 到 Production:Agent Runtime 的失败恢复与验证闭环
人工智能
土星云SaturnCloud1 小时前
边缘计算赋能电子焊接工位双摄AI管控:土星云SE110S-WC8实现合规检测与质量追溯全闭环
服务器·人工智能·ai·边缘计算
月光船幽幽2 小时前
分层阈值规避归藏协议过度重置
人工智能·python