资讯动态

RHEL 8 上基于 GPU 的深度强化学习机器人训练实战

发布时间:2026/10/19 20:03:10 来源:尧图企业网站定制
1. 为什么 RHEL 8 会成为机器人训练环境的默认选择接手一个 AI 机器人决策系统训练任务时我首先面对的不是算法本身而是服务器环境。那台新采购的 GPU 服务器预装 RHEL 8要在上面跑深度强化学习训练前后折腾了几天把驱动、容器、框架、仿真环境一路打通后训练速度比之前的 CPU 方案快了一个数量级整个开发节奏才终于顺起来。这篇内容就是把这几天做的事情完整整理一遍给准备在 RHEL 8 上做同样事情的开发者一个可以直接参考的路线图。1.1 生命周期、仓库体系与运维手感选择 RHEL 8 作为训练环境的理由一开始听上去不太“极客”但实际用起来非常实在它是一个有 10 年支持周期的企业级系统。深度强化学习训练任务动不动连续跑几天如果系统每半年要强制升级一次或者某个依赖库因为系统滚动更新悄悄变了版本整个训练可能直接报废。RHEL 8 的更新策略更接近“可控的稳定”运维上可以指定更新窗口这对长期跑 GPU 训练任务来说比“永远最新”重要得多。仓库体系也帮了大忙。RHEL 8 默认的 DNF 比老一代 YUM 快了不少模块流AppStream允许在同一套系统上按需启用不同版本的 Python比如dnf module enable python39之后就能用 Python 3.9不用自己编译安装解释器。相比在别的发行版上折腾 Python 版本冲突RHEL 8 这种方式对训练框架依赖的 Python 版本管理非常友好。再加上 CodeReady Builder 仓库补全了一部分开发库大部分基础依赖都能用包管理器直接解决。如果你之前主要用 Ubuntu 做深度学习可能觉得 RHEL 的软件包比较“老”。但换个角度想训练框架真正依赖的是 CUDA 运行时和系统底层库RHEL 的 glibc 版本稳定反而不容易出现“升级一半导致某个 .so 找不到”的连锁反应。一次安装、长期稳定对我来说比尝鲜新版本更有价值。1.2 GPU 究竟加速了深度强化学习的哪一部分很多人以为深度强化学习训练的主要计算量在神经网络梯度更新上因此 GPU 一上整个训练都会自动提速。实际不完全是这样。机器人决策系统的训练循环大致分三段智能体在仿真环境里采样、用采样数据更新策略网络、评估当前策略效果。采样阶段主要靠 CPU 跑物理模拟器策略更新阶段才用 GPU 计算梯度。如果只有一个仿真环境哪怕你用四卡 A100采样速度也上不去GPU 大部分时间在空转。GPU 真正的价值在于支撑“大规模并行采样”。策略梯度类算法需要大量轨迹数据来估计优势函数数据量越充足梯度方向越稳定。单环境串行采样时Agent 几百万步交互可能要跑几天但在 GPU 服务器上你可以同时拉起几十个甚至上百个仿真环境每个环境独立跑自己的轨迹统一把样本喂给 GPU 做批量更新。这个过程就好比 CPU 训练是“一个学生埋头做题”GPU 服务器则是“上百个学生同时刷题老师用 GPU 高速批改作业”吞吐量差出一个数量级。所以标题里“基于 GPU 的深度强化学习训练”本质上包含两个部分GPU 负责策略网络的快速学习和批量推理CPU 多核配合负责仿真环境的并行推进。RHEL 8 在这套组合里扮演的是“稳定基座”的角色把驱动、运行时、容器和训练框架之间的兼容性问题一次性消化掉让后续的算法开发可以专注在决策逻辑本身。2. RHEL 8 下的 GPU 环境搭建驱动、CUDA 与容器2.1 驱动安装前先锁死内核与 Nouveau 驱动RHEL 8 默认自带的开源驱动 Nouveau 在 NVIDIA 显卡上能用但跑 CUDA 训练需要闭源驱动所以安装前第一件事就是禁掉 Nouveau。这个步骤顺序不能反如果你直接装 NVIDIA 驱动系统里 Nouveau 还占着设备驱动加载会冲突表现通常是nvidia-smi能输出但 CUDA context 初始化失败或者直接报 no device。先安装编译驱动需要的工具链再写黑名单。内核开发包要和当前内核版本严格一致否则 DKMS 编译会失败# 安装基础编译工具注意 kernel-devel 版本与 uname -r 保持一致 dnf install -y kernel-devel-$(uname -r) gcc gcc-c make dkms # 禁用 nouveau cat /etc/modprobe.d/blacklist-nouveau.conf EOF blacklist nouveau options nouveau modeset0 EOF # 重新生成 initramfs dracut --force改完需要重启才能让 nouveau 真正不再加载。重启后可以确认一下lsmod | grep nouveau没有输出就说明干净了。另一个容易忽略的问题是 Secure Boot。如果机器开启了 Secure Boot 又没有做驱动签名NVIDIA 内核模块会被拒绝加载。最省事的做法是在服务器 BIOS 里关掉 Secure Boot如果公司安全策略不允许关那就要走 DKMS 签名流程把 MOK 导入 UEFI。这一步看起来繁琐但如果你跳过了后续每次内核更新都可能在重启后遇到驱动消失排查起来比直接关掉痛苦得多。2.2 仓库安装和 runfile 安装怎么选NVIDIA 驱动和 CUDA 在 RHEL 8 上有两条主流安装路径我实际比较下来更推荐 DNF 仓库方式。先添加 NVIDIA 的 CUDA 仓库然后直接安装驱动模块和 CUDA 工具包dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel8/x86_64/cuda-rhel8.repo dnf clean all # 查看可用的驱动模块流 dnf module list nvidia-driver # 安装带 DKMS 的驱动版本内核更新后能自动重新编译 dnf module install -y nvidia-driver:latest-dkms # 安装指定版本的 CUDA 工具包这里以 12.4 为例 dnf install -y cuda-toolkit-12-4这套方式的优势在于驱动会进入系统包管理升级内核时 DKMS 会自动重编模块不会出现重启后驱动神秘消失的情况。runfile 方式适合完全离线的机器或者你有特殊理由必须装某个特定小版本驱动。但 runfile 安装后驱动不在 DNF 管理范围内后续dnf update升级内核很容易导致驱动与内核失配需要手动重装。除非网络条件极度受限否则我不会推荐 runfile。安装完成后的环境变量也很关键。RHEL 8 下 CUDA 默认装在/usr/local/cuda需要把下面两行加进/etc/profile.d/cuda.sh或者用户 shell 配置里export PATH/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda/lib64:$LD_LIBRARY_PATHCuDNN 我习惯用 tar 包形式解压后拷到 CUDA 目录这样不用额外维护 RPM 依赖。下载对应 CUDA 版本的 cuDNN 后执行tar -xvf cudnn-linux-x86_64-*.tar.xz cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda/include/ cp cudnn-*-archive/lib/libcudnn* /usr/local/cuda/lib64/ chmod ar /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*2.3 验证 GPU 是否真正可用驱动和 CUDA 装好后不要急着开训练。用一套最简单的验证链路确认每个环节都通了# 查看显卡与驱动状态 nvidia-smi # 确认 CUDA 编译器版本 nvcc --version # 用 Python 验证 PyTorch 能看到 GPU python3 -c import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))如果torch.cuda.is_available()返回 False优先检查两个地方PyTorch 安装的是否为 CUDA 版本不是 CPU 版以及/usr/local/cuda/lib64是否在LD_LIBRARY_PATH里。在 RHEL 8 上最容易出现的情况是驱动正常nvidia-smi正常但torch报找不到libcudart.so.12原因就是 CUDA 运行时路径没有导出。把环境变量配上再重新打开 Python 就好。提示RHEL 8 自带的 Python 3.6 太老建议用dnf module enable python39装 Python 3.9 或 3.11训练框架对版本的要求通常比较宽容但 3.6 很难满足。2.4 用 Podman 容器隔离训练环境RHEL 8 上默认的容器工具是 Podman不需要装 Docker。训练环境的依赖链很长PyTorch、模拟器、各种 Python 包互相之间版本敏感我强烈建议把训练环境装进容器而不是直接装在宿主机上。这样哪怕某个包把系统库搞坏了也不会影响机器的其他服务。NVIDIA 容器运行时配好后Podman 可以直接把 GPU 映射进容器dnf install -y podman nvidia-container-toolkit # 配置 NVIDIA 容器运行时的 Podman 支持之后 --gpus all 就能用 nvidia-ctk runtime configure --runtimepodman容器运行命令大致如下podman run --rm --gpus all --shm-size1g \ -v /data/train:/train:Z \ -v /home/you/code:/code:Z \ nvcr.io/nvidia/pytorch:24.04-py3 \ python3 /code/train.py:Z参数是 RHEL 8 特有的细节它让 Podman 自动调整挂载目录的 SELinux 标签不加的话容器里经常遇到 Permission denied而且这个报错不会指向 SELinux排查起来很迷惑。共享内存参数--shm-size也值得注意深度强化学习中多进程采样需要大量共享内存做数据交换默认 64MB 很容易触发异常。3. 机器人决策场景中的深度强化学习技术选型与最小实现3.1 算法选型PPO 为什么是默认起点机器人决策系统的动作空间通常是连续的比如机械臂各关节的力矩、移动机器人的线速度和角速度。老牌的 DQN 在离散动作场景表现好但连续控制里要把动作离散化精度和维度都受限制。SAC 和 PPO 是连续控制领域最常见的两个选择。SAC 样本效率更高但调参敏感对奖励尺度比较挑剔PPO 的 clipped objective 限制了单次更新幅度训练曲线更稳定超参不那么敏感工程落地时踩坑概率低。如果你负责的项目还处于“能不能学会某个任务”的验证阶段我建议直接上 PPO。它的核心思路可以拆成三段用当前策略在环境里采集一批轨迹用 Generalized Advantage EstimationGAE计算每个状态动作对的优势值通过截断的损失函数更新 Actor 和 Critic 网络。这套流程思想简单实现成熟Stable-Baselines3 和 RLlib 都有开箱即用的版本不用自己造轮子。3.2 仿真环境与奖励函数设计训练环境不能直接在真实机器人上跑否则前期乱探索的阶段很可能把硬件弄坏。常规做法是在仿真器里定义一个符合 Gym API 的环境。观察空间通常是传感器数据加机器人状态比如关节角度、关节角速度、末端执行器坐标、受力反馈动作空间则是机器人控制指令。封装时只要实现两个方法reset()返回初始观测step(action)返回新的观测、奖励、是否结束和额外信息。奖励函数是整个训练里最靠“手艺”的部分。稀疏奖励“完成任务给 1 分其余给 0”训练难度很大因为探索阶段几乎拿不到反馈Agent 找不到学习的梯度方向。我一般会拆成稠密奖励给靠近目标的距离变化设置奖励增量给过大加速度设置小惩罚给完成任务一个较大的正向奖励。但稠密奖励也有副作用Agent 可能学会“原地抖一抖刷距离差值”这就是常见的 Reward Hacking。设计奖励时一定要反复问自己这个奖励函数是不是在鼓励机器人完成我真正想让它做的事而不是“刷分”。MuJoCo 这类物理仿真库被广泛使用不是因为开源免费而是它求解接触和关节约束足够稳定训练轨迹的可重复性好。如果你要训练的机器人有特殊结构可能要用自己的内部仿真器但暴露给算法层面的接口同样建议遵循 Gym 规范这样后续换算法库、换训练框架都不用重写环境接口。3.3 一个最小可跑的 PPO 训练核心片段用 Stable-Baselines3 跑一个 PPO 训练任务代码量其实非常小。下面这段是基于向量化环境的训练骨架实际项目里可以直接套用from stable_baselines3 import PPO from stable_baselines3.common.vec_env import SubprocVecEnv import gymnasium as gym def make_env(rank): def _init(): env gym.make(YourRobotEnv-v0) env.reset(seed1000 rank) return env return _init # 32 个并行环境充分利用 CPU 多核和 GPU 批量推理 env SubprocVecEnv([make_env(i) for i in range(32)]) model PPO( MlpPolicy, env, n_steps2048, batch_size256, gamma0.99, gae_lambda0.95, clip_range0.2, learning_rate3e-4, verbose1, ) model.learn(total_timesteps5_000_000) model.save(robot_ppo_v1)这里的n_steps2048表示每个并行环境每次 rollout 采集 2048 步32 个环境一次就能拿到 65536 条真实交互样本这是 GPU 服务器相比单机环境最大的吞吐优势。batch_size 是更新网络的 batch注意不要设得太大否则 GPU 显存和训练稳定性都会受影响。如果你需要更大的分布式规模RLlib 提供了另一套现成方案。它的设计思路是采样和训练解耦多个 rollout worker 分布在不同 CPU 核上采样Learner 在 GPU 上更新。配置如下from ray.rllib.algorithms.ppo import PPOConfig config ( PPOConfig() .environment(YourRobotEnv-v0) .resources(num_gpus4, num_cpus_per_worker1) .rollouts(num_rollout_workers64, rollout_fragment_length200) .training(train_batch_size4096, sgd_minibatch_size512, lr3e-4) ) algo config.build_algo() for i in range(200): result algo.train() print(fiter{i}, reward{result[episode_reward_mean]:.2f})4. 训练加速的几条真实路径并行环境、混合精度与多卡4.1 环境并行的配置比更换 GPU 更有效很多人拿到新服务器第一反应是“GPU 越多越好”但在深度强化学习场景环境并行的收益往往来得比堆 GPU 更直接。采样瓶颈卡在仿真器上时GPU 再快也只能干等。通用做法是让仿真环境的进程数约等于物理 CPU 核心数减一两个留给系统和其他进程余量。Stable-Baselines3 的SubprocVecEnv是标准做法每个环境跑在独立进程中避免 Python GIL 的限制。如果你用 Podman 容器跑训练记得要给容器足够的 CPU 限制podman run --cpuset-cpus0-47这类参数可以避免采样进程被调度到同一个核心上抢资源。共享内存这里再强调一次进程通信大量依赖共享内存--shm-size1g是我踩过坑之后养成的固定习惯。4.2 混合精度在 DRL 里的正确姿势混合精度AMP在图像分类这类任务上几乎是免费的加速但深度强化学习里要谨慎一点。Critic 网络对价值函数的数值精度比较敏感奖励的尺度差异也大如果直接照搬分类任务的 AMP 配置训练曲线可能突然发散。我的建议是先用 FP32 把任务跑通确认策略能收敛再开 AMP 做加速实验。开启时用 PyTorch 的autocast只包裹前向和损失计算部分不要对 GAE 这类数值累计逻辑使用低精度。回放缓冲区里的数据继续用 FP32 存储只有在进 GPU 计算时才降精度这样既保住了训练稳定性又能让 V100 及更新架构上的 Tensor Core 发挥作用。A100/H100 这类卡上 FP16 算力是 FP32 的数倍收益明显如果是 T4 或更低端的卡收益有限不用花太多精力折腾。4.3 从单卡到多卡DDP 与 RLlib 的分布式配置单卡训练能跑通后多卡扩展是提升吞吐的直接手段。PyTorch 的DataParallel在多卡场景下固有同步开销主进程容易成为瓶颈真正的多卡训练应该用DistributedDataParallel它让每个进程独立管理一张卡只在反向传播时同步梯度。下面是一个最小 DDP 启动思路# 4 张卡对应 4 个进程 python3 -m torch.distributed.run --nproc_per_node4 train_ddp.pytrain_ddp.py里要做的事包括根据LOCAL_RANK给不同进程分配 GPU、把模型搬到对应设备、用 DistributedSampler 切分数据。深度强化学习里 DDP 的要点是rollout 在每个进程里独立采样然后用 all-reduce 同步梯度更新。这能保证每个 GPU 都能吃到相对独立的数据策略更新信息又在多卡之间共享。如果你不想手写这套分布式逻辑RLlib 是更省事的选择。把num_gpus4配进去后它自己会处理 Learner 的 GPU 分配和梯度同步。需要注意num_workers和num_gpus的配合不要超过实际机器资源否则 Ray 调度时大量时间花在资源等待上看起来配置很大实际吞吐反而不升。4.4 先看瓶颈再优化用 nvidia-smi 和 TensorBoard 判断问题不要盲目调超参先看训练时 GPU 到底在干什么。我习惯每隔一段时间记录一次nvidia-smi的输出把 GPU-Util、显存占用和 CPU 负载综合起来判断瓶颈位置。现象通常瓶颈建议GPU-Util 低CPU 占用率高环境采样、物理仿真太慢增加并行环境数或优化仿真器步长GPU-Util 高CPU 占用率较低网络计算是主要开销开启 AMP增大 batch 提升 Tensor Core 利用率GPU-Util 和 CPU 都低数据同步、进程调度、共享内存瓶颈检查--shm-size减少 worker 数量或调整亲和性显存缓慢增长训练一段时间后 OOM显存泄漏或缓存未释放定位未释放的 Tensor检查是否每轮迭代累积了 graph 缓存TensorBoard 也要用起来。除了 reward 曲线我每次都会记录entropy、clip_fraction、approx_kl。如果clip_fraction接近 0.3 以上说明每步更新幅度太大策略在剧烈震荡如果 KL 散度过大说明新旧策略差异拉得太开通常需要降低学习率或减小 rollout 步数。这些指标比单一 reward 曲线更能提前暴露问题。5. 从训练集群到真实机器人模型导出与推理部署5.1 导出TorchScript 与 ONNX 的正确打开方式训练只是第一步机器人决策系统最终要把策略网络部署到真实机器人上运行。这一步遇到的第一堵墙是“训练代码依赖大量 Python 库不能直接搬到机器人主控里”。常规做法是把策略网络导出成轻量格式再做推理。PyTorch 训练出的 Actor 网络如果只是几层 MLPtorch.jit.trace是最简单的导出方式。Trace 对控制流简单的网络效果很好import torch # 假设 model.policy 是 SB3 训练好的 ActorCriticPolicy policy model.policy policy.eval() obs_dim 17 # 你的观察空间维度 dummy_obs torch.randn(1, obs_dim) # 导出确定性动作取分布均值避免推理时引入随机噪声 traced torch.jit.trace(policy.actor, dummy_obs) traced.save(robot_policy.pt)注意深度强化学习的策略网络在训练时通常输出一个动作分布比如高斯分布的均值和标准差。部署到机器人上如果用带随机性的采样动作控制效果会明显抖动。真实控制系统应该使用分布的均值确定性策略作为输出导出时要固定这条路径。ONNX 是另一种选择好处是跨平台、跨框架。导出方式类似torch.onnx.export( policy.actor, dummy_obs, robot_policy.onnx, input_names[obs], output_names[action], dynamic_axes{obs: {0: batch}, action: {0: batch}}, opset_version17, )5.2 TensorRT 加速与推理延迟的实测取舍模型部署到机器人上通常对推理延迟有硬性要求。决策控制频率如果是 30Hz单次推理必须在 33ms 内完成如果控制频率要到 100Hz留给推理的时间只有 10ms 以内。对大多数只有几层 MLP 的策略网络来说ONNX Runtime GPU 和直接 PyTorch CUDA 推理已经能满足毫秒级延迟TensorRT 的收益未必明显。TensorRT 真正有价值的场景是策略网络包含卷积层、或者需要在边缘设备上连续跑多个模型。转换命令很直接trtexec --onnxrobot_policy.onnx --saveEnginerobot_policy.engine --fp16FP16 引擎通常能让网络密集型推理快一到两倍但不建议直接上 INT8。强化学习策略对输入的小扰动很敏感INT8 量化极有可能在边界输入上输出明显偏差的动作机器人控制里这可能导致硬件碰撞。如果一定要 INT8得在真实传感器数据分布上做校准而不是拿随机张量校准。还有一点容易忽略推理端输入数据的预处理时延。机器人传感器数据往往是 numpy 数组在 CPU 上要拷贝到 GPU 再变成 Tensor。这个 H2D 拷贝有时比网络推理本身还慢。数据量小时甚至纯 CPU 推理会更低延迟因为省了拷贝开销。部署前一定要做端到端延迟测试不要只看模型推理时间。5.3 与机器人中间件的集成准备实际机器人主控里的部署不会是一个孤立 Python 文件而是要和机器人中间件通信。常见做法是把策略推理封装成一个节点订阅传感器数据话题发布动作指令话题。关键设计有两点一是决策频率要有超时保护如果传感器话题超过一定时间没有新数据节点必须进入安全模式而不是一直用旧数据推断二是动作输出要做边界限幅和速率限制防止策略网络偶发异常输出导致执行器速度突变。训练环境和真实环境的差异是部署阶段最大的不确定因素。仿真的物理参数、摩擦系数、传感器噪声分布都不可能和真实机器人完全一致。我见过不少项目训练时表现很好真机上第一分钟就撞墙。缓解措施包括训练时对观测加入随机扰动对动作执行添加噪声在仿真中随机化物理参数这些工程技巧能显著缩小 sim-to-real 的差距。即使如此真机测试的第一轮建议用很小的动作限幅人工准备好急停跑通一轮后再逐步放开限制。训练曲线再漂亮没有安全兜底部署风险都是不可接受的。如果目标机器人主控性能很弱连 GPU 都没有可以把策略模型部署在单独的边缘推理设备上通过局域网和主控通信。边缘设备上同样优先导出 ONNX 或 TensorRT 引擎用起来比直接跑 PyTorch 更可控也更容易做多语言集成。6. 我在实际搭建中踩过的几个坑与绕法6.1 内核更新后驱动失配CUDA 找不到设备某次例行维护后服务器重启进入系统nvidia-smi直接报错找不到设备。查下来是dnf upgrade自动更新了内核DKMS 在 RHEL 8 上虽然装了但未必每次都自动重编成功。遇到这种情况不要急着卸载驱动先看 DKMS 状态dkms status如果模块是“missing”之类的状态手动重建一次dkms autoinstall --force modprobe nvidia这个坑的核心教训是训练服务器千万不要随手执行无脑dnf update。更新前先看更新列表里有没有 kernel有的话要么只排除内核更新要么把驱动重编纳入计划。稳定的训练中断远比一个“最新内核”值得。6.2 RLlib 环境序列化失败多 worker 报 obscure pickle 错误第一次在 RHEL 8 上用 RLlib 训练自定义机器人环境设置了 16 个 rollout worker结果 worker 一启动就报错说环境无法被序列化。查了半天发现原因是我把环境类直接定义在训练脚本的__main__里Ray 要把环境定义发到不同 worker 进程去实例化但 Python 的 pickle 无法对“主模块里的局部类”做序列化。解决办法很简单把环境类放进独立模块文件比如envs/robot_env.py然后在训练脚本里用from envs.robot_env import YourRobotEnv。另外还要确认训练脚本运行时的PYTHONPATH包含了项目根目录否则 worker 进程导入不到这个模块。这个坑和 RHEL 8 本身关系不大但容器化环境下更容易被隐藏的路径差异放大多进程问题。6.3 训练中断后显存不释放下一轮训练直接 OOM训练任务被 CtrlC 中断后GPU 显存偶尔还是满的启动下一轮训练直接报 CUBLAS_STATUS_ALLOC_FAILED。原因通常是 PyTorch 子进程里存在未被销毁的采样 worker或者 Julia 这样的外部进程残留了 CUDA context。处理方式# 查看占用 GPU 的进程 nvidia-smi --query-compute-appspid,used_memory --formatcsv # 确认是残留进程后结束它 kill -9 pid如果只看nvidia-smi上半部分显存占用但下半部分没有进程列表说明可能是 CUDA context 挂空。这时候fuser -v /dev/nvidia*可以定位到具体进程。为了避免这个问题训练脚本里最好注册信号处理器在 CtrlC 时主动调用env.close()和torch.cuda.empty_cache()。代码里做一层“优雅退出”比每次中断后手动清理省心得多。6.4 容易被忽视的隐性加速项温度功耗墙与持久模式有段时间训练速度非常不稳定前几个小时正常后面某个时间点开始掉速严重。看nvidia-smi发现 GPU 温度到了 85℃ 以上显存时钟和核心时钟都在明显下降。机房散热余量不足导致 GPU 触发了功耗墙这属于环境问题再调整代码也没用。后来给服务器补了散热、改善了风道又对 GPU 开启了持久模式nvidia-smi -pm 1持久模式让显卡驱动常驻每次调用 CUDA 运行时不需要重新初始化能省掉一小部分启动开销。另一个隐性因素是磁盘。深度强化学习如果开了大容量经验回放且频繁读写中间缓存机械硬盘或网络盘的 IO 延迟会直接拖慢训练循环。建议回放数据和 checkpoint 都放到 NVMe SSD 上这类开销在现代深度学习训练里不容易被注意到但对整轮训练的实际耗时影响非常明显。最后补一个我现在已经固化下来的习惯任何深强化学习项目开始前先写一份环境版本清单包括内核版本、驱动版本、CUDA 版本、cuDNN 版本、PyTorch 版本、训练框架版本保存成文本放在项目目录里。手动整理这份清单的收益在三四个月后回来看这个项目时特别明显否则根本记不清当时的训练结果是在哪套环境组合下跑出来的复现实验就会变成碰运气。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑