RF-DETR + DeepSpeed 双节点集群训练环境搭建操作记录

测试环境:两台 Windows 11 主机,每台配备一张 NVIDIA GeForce RTX 5080。


1. 准备 Windows 11 与 WSL 2 环境

在两台主机上分别完成以下操作。

  1. 打开 任务管理器 → 性能 → CPU,确认 CPU 虚拟化已启用。

  2. 在命令行中检查 WSL 状态:

    powershell 复制代码
    wsl --status
  3. 若提示"WSL 2 无法启动,因为此计算机上未启用虚拟化",执行:

    powershell 复制代码
    wsl.exe --install --no-distribution

    执行完成后重启主机。

  4. 重启后再次验证:

    powershell 复制代码
    wsl --status
  5. 确保已安装 Linux 发行版,例如 Ubuntu。


2. 准备 Docker 与网络环境

2.1 安装 Docker

在 Ubuntu 中执行:

bash 复制代码
sudo apt update
sudo apt install -y ca-certificates curl

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fL \
  https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
ls -lh /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |
  sudo tee /etc/apt/sources.list.d/docker.list >/dev/null

sudo apt update
sudo apt install -y \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin
修复 Docker 用户权限

如果执行 docker ps 时出现以下错误,但使用 sudo docker ps 可以正常运行:

text 复制代码
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock

执行以下命令,将当前用户加入 docker 用户组:

bash 复制代码
getent group docker || sudo groupadd docker
sudo usermod -aG docker "$USER"
newgrp docker

2.2 配置 WSL 镜像网络

为 Ubuntu 配置镜像网络,使 Windows 主系统与 WSL 使用一致的网络地址,便于后续搭建集群。

在 Windows PowerShell 中执行:

powershell 复制代码
notepad $env:USERPROFILE\.wslconfig

写入以下配置:

ini 复制代码
[wsl2]
networkingMode=mirrored
dnsTunneling=true
autoProxy=true

[experimental]
hostAddressLoopback=true

保存文件后,在 PowerShell 中关闭 WSL:

powershell 复制代码
wsl --shutdown

重新启动 Ubuntu,使配置生效。

2.3 配置本地镜像库

配置本地镜像库,以便各节点拉取已经构建完成的训练镜像。镜像构建文件参见本文附录。


3. 准备工作目录与 SSH 密钥

以下目录仅为示例,可根据实际挂载方式调整:

bash 复制代码
mkdir -p \
  app \
  data \
  output \
  .cache/rfdetr-models \
  "$HOME/.rfdetr-cluster"

目录用途如下:

目录 用途
app 存放训练与执行脚本
data 存放训练数据
output 存放训练输出、检查点等文件
.cache/rfdetr-models 缓存模型预训练权重
$HOME/.rfdetr-cluster 存放 SSH 密钥、known_hosts 等集群访问文件

共享存储建议

前四个目录均可挂载到共享存储,其中 output 应挂载到所有训练节点均可访问的公共存储。

3.1 在第一台主机上生成 SSH 密钥

bash 复制代码
ssh-keygen \
  -t ed25519 \
  -N "" \
  -f "$HOME/.rfdetr-cluster/id_ed25519"

touch "$HOME/.rfdetr-cluster/known_hosts"
chmod 700 "$HOME/.rfdetr-cluster"
chmod 600 "$HOME/.rfdetr-cluster/id_ed25519"
chmod 644 "$HOME/.rfdetr-cluster/id_ed25519.pub"
chmod 644 "$HOME/.rfdetr-cluster/known_hosts"

3.2 同步密钥与目录

在第二台主机上创建相同的目录结构。

如果希望任意一台主机都能作为主节点(Master Node),将第一台主机生成的密钥对复制到第二台主机的相同路径,并保持相同的文件权限。


4. 安装 NVIDIA Container Toolkit

在两台主机的 Ubuntu 环境中分别执行以下命令,以确保 Docker 容器能够访问 GPU:

bash 复制代码
sudo apt-get update
sudo apt-get install -y curl gpg

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
  | sudo gpg --dearmor \
      -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
  | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
  | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

5. 测试节点互通

5.1 写入 SSH 主机指纹

在两台主机上分别启动容器,并将两个节点的 SSH 主机指纹写入 known_hosts

bash 复制代码
ssh-keyscan \
  -p 2222 \
  -H "192.168.1.xxx" "192.168.1.yyy" \
  > "$HOME/.rfdetr-cluster/known_hosts"

其中:

  • 192.168.1.xxx:第一台主机的 IP 地址;
  • 192.168.1.yyy:第二台主机的 IP 地址。

5.2 双向测试 SSH 与 GPU 访问

192.168.1.xxx 节点上执行:

bash 复制代码
docker exec \
  -u trainer \
  rfdetr-node \
  ssh -p 2222 192.168.1.yyy nvidia-smi -L

随后在 192.168.1.yyy 节点上执行反向测试,确保两个节点之间均可通过 SSH 访问,并能够识别远端 GPU。


6. 验证容器训练环境

进入训练容器:

bash 复制代码
docker exec -it \
  -u trainer \
  rfdetr-node \
  bash

进入容器后,执行以下脚本,验证 PyTorch、DeepSpeed、CUDA、BF16 和 GPU 矩阵运算:

bash 复制代码
python - <<'PY'
import torch
import deepspeed

print("PyTorch:", torch.__version__)
print("DeepSpeed:", deepspeed.__version__)
print("PyTorch CUDA:", torch.version.cuda)
print("CUDA available:", torch.cuda.is_available())

assert torch.cuda.is_available(), "PyTorch 无法访问 CUDA"

print("GPU:", torch.cuda.get_device_name(0))
print("Compute capability:", torch.cuda.get_device_capability(0))
print("BF16 supported:", torch.cuda.is_bf16_supported())

x = torch.randn(2048, 2048, device="cuda")
y = x @ x
torch.cuda.synchronize()

print("GPU calculation: OK")
print("Result checksum:", y.sum().item())
PY

7. 执行双节点训练测试

7.1 创建 DeepSpeed Hostfile

调整好数据和输出目录的挂载位置后,在主节点容器中写入本次参与训练的节点 IP。Hostfile 中需要同时包含主节点自身。

bash 复制代码
printf '%s\n' \
  '192.168.1.xxx slots=1' \
  '192.168.1.yyy slots=1' \
  > /tmp/deepspeed-hostfile

7.2 启动训练

确保两个节点上存在完全相同的训练脚本,然后在主节点执行:

bash 复制代码
deepspeed \
  --hostfile /tmp/deepspeed-hostfile \
  --ssh_port 2222 \
  --master_addr 192.168.1.xxx \
  --master_port 29500 \
  /workspace/app/train_seg_cluster.py

参数说明:

参数 说明
--hostfile DeepSpeed 节点与 GPU 插槽配置文件
--ssh_port 节点容器的 SSH 端口
--master_addr 主节点 IP 地址
--master_port 分布式通信端口
/workspace/app/train_seg_cluster.py 训练入口脚本

附录

A. Dockerfile

dockerfile 复制代码
FROM pytorch/pytorch:2.12.1-cuda13.0-cudnn9-devel@sha256:ac63aaae09996612bdaf12bbf6d5fe840af6bed3100d6dc15fcb5fd1f4f957c4

ARG DEBIAN_FRONTEND=noninteractive

ENV VIRTUAL_ENV=/opt/venv \
    PATH=/opt/venv/bin:${PATH} \
    PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PDSH_RCMD_TYPE=ssh

RUN apt-get update \
    && apt-get install --yes --no-install-recommends \
        build-essential \
        ca-certificates \
        git \
        iproute2 \
        iputils-ping \
        ninja-build \
        openssh-client \
        openssh-server \
        pdsh \
        python3-venv \
    && rm -rf /var/lib/apt/lists/*

RUN python -m venv --system-site-packages "${VIRTUAL_ENV}" \
    && "${VIRTUAL_ENV}/bin/python" -m pip install --no-cache-dir --upgrade pip \
    && DS_BUILD_OPS=0 "${VIRTUAL_ENV}/bin/python" -m pip install --no-cache-dir \
        "rfdetr[train,loggers]==1.8.3" \
        "pytorch-lightning==2.6.5" \
        "deepspeed==0.19.3"

RUN set -eux; \
    existing_group="$(getent group 1000 | cut -d: -f1 || true)"; \
    if [ -z "${existing_group}" ]; then \
        groupadd --gid 1000 trainer; \
    elif [ "${existing_group}" != trainer ]; then \
        groupmod --new-name trainer "${existing_group}"; \
    fi; \
    existing_user="$(getent passwd 1000 | cut -d: -f1 || true)"; \
    if [ -z "${existing_user}" ]; then \
        useradd --create-home --uid 1000 --gid 1000 --shell /bin/bash trainer; \
    elif [ "${existing_user}" != trainer ]; then \
        usermod --login trainer --home /home/trainer --move-home --shell /bin/bash "${existing_user}"; \
    fi; \
    passwd --delete trainer; \
    install -d -m 0755 -o trainer -g trainer /workspace/app /workspace/data /workspace/output; \
    install -d -m 0700 -o trainer -g trainer /home/trainer/.ssh; \
    printf '%s\n' \
        'Host *' \
        '    User trainer' \
        '    IdentityFile /home/trainer/.ssh/id_ed25519' \
        '    IdentitiesOnly yes' \
        > /etc/ssh/ssh_config.d/99-cluster.conf; \
    printf '%s\n' \
        'PubkeyAuthentication yes' \
        'PasswordAuthentication no' \
        'KbdInteractiveAuthentication no' \
        'PermitRootLogin no' \
        'AllowUsers trainer' \
        > /etc/ssh/sshd_config.d/99-cluster.conf; \
    ssh-keygen -A

WORKDIR /workspace/app

B. compose.yaml

yaml 复制代码
name: rfdetr-cluster

services:
  node:
    image: <image name>
    container_name: rfdetr-node
    hostname: rfdetr-node
    network_mode: host
    ipc: host
    init: true
    restart: unless-stopped
    working_dir: /workspace/app
    command:
      - /bin/sh
      - -c
      - |
        install -d -m 0755 -o root -g root /run/sshd
        exec /usr/sbin/sshd -D -e -p 2222
    environment:
      HOME: /home/trainer
      PDSH_RCMD_TYPE: ssh
      PDSH_SSH_ARGS_APPEND: "-p 2222"
      NCCL_IB_DISABLE: "1"
      NCCL_SOCKET_FAMILY: AF_INET
      NCCL_SOCKET_IFNAME: eth0
      NCCL_DEBUG: WARN
    ulimits:
      memlock: -1
      stack: 67108864
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    volumes:
      - ./app:/workspace/app
      - ./data:/workspace/data
      - ./output:/workspace/output
      - .cache/rfdetr-models:/home/trainer/.roboflow/models
      - $HOME/.rfdetr-cluster/id_ed25519:/home/trainer/.ssh/id_ed25519
      - $HOME/.rfdetr-cluster/id_ed25519.pub:/home/trainer/.ssh/authorized_keys
      - $HOME/.rfdetr-cluster/known_hosts:/home/trainer/.ssh/known_hosts

C. train_seg_cluster.py

python 复制代码
import os
import socket

# DeepSpeed launcher 使用 CROSS_RANK 表示节点编号;
# Lightning 默认读取 NODE_RANK 或 GROUP_RANK。
if "CROSS_RANK" in os.environ:
    os.environ["NODE_RANK"] = os.environ["CROSS_RANK"]
    os.environ["GROUP_RANK"] = os.environ["CROSS_RANK"]

import torch
from pytorch_lightning.strategies import DeepSpeedStrategy, StrategyRegistry
from rfdetr import RFDETRSegLarge

DATASET_DIR = "/workspace/data/task1"
OUTPUT_DIR = "/workspace/output/task1"
STRATEGY_NAME = "deepspeed_stage_0"

def main() -> None:
    if not torch.cuda.is_available():
        raise RuntimeError("CUDA is not available.")

    StrategyRegistry.register(
        STRATEGY_NAME,
        DeepSpeedStrategy,
        description="DeepSpeed with ZeRO Stage 0",
        stage=0,
    )

    print(f"Using CUDA device: {torch.cuda.get_device_name(0)}")

    model = RFDETRSegLarge(amp=False)

    model.train(
        dataset_dir=DATASET_DIR,
        output_dir=OUTPUT_DIR,
        epochs=100,
        batch_size=1,
        grad_accum_steps=4,
        num_workers=2,
        device="cuda",
        strategy=STRATEGY_NAME,
        devices=1,
        num_nodes=2,
        tensorboard=True,
        progress_bar="tqdm",
        checkpoint_interval=50,
        eval_interval=1,
        use_ema=False,
    )

if __name__ == "__main__":
    main()
相关推荐
今天AI了吗1 小时前
【AI智能体】Hermes Agent 从部署到项目实战操作详解
java·人工智能·python·milvus
心运软件2 小时前
基于机器学习的智能邮件分类系统:从数据采集到模型部署全流程实战
人工智能·python·算法·随机森林·机器学习·分类·scikit-learn
ZHOU_WUYI2 小时前
5. fastwam 模型 video expert pre dit过程
pytorch·python·世界动作模型
过期的秋刀鱼!3 小时前
机器学习开发的迭代循环
人工智能·python·深度学习·神经网络·机器学习
小白学大数据3 小时前
基于Python的抖音网页版视频点赞数增长趋势追踪系统设计与实现
开发语言·爬虫·python·搜索引擎·音视频
circuitsosk3 小时前
平台整体能力与功能特性设计:分群、联运、ABTest与运营位系统
python·机器学习·搜索引擎·ab测试·vllm·rag检索
Livia要学习3 小时前
Python三种常见高阶函数--map、filter、sorted
开发语言·python
冷咖啡离 我的笨笨4 小时前
用最简单的例子,从最简单的设计开始,重构着讲解设计原则与模式——从DIP中“倒置”的含义说接口的正确使用
python·重构·依赖倒置原则
PC2005-cloud4 小时前
FinalShell 自定义背景图片教程
ide·python·pycharm