MirroredStrategy适用于单机多卡同步数据并行训练,需将模型构建、优化器等全置于strategy.scope()内,全局batch size=每卡batch×卡数,梯度聚合须用strategy.reduce,且需通过CUDA_VISIBLE_DEVICES显式指定GPU并验证num_replicas_in_sync。

TensorFlow 原生多 GPU 并行不是“开个开关就能用”,关键得看你是用 tf.distribute.MirroredStrategy 还是手动设备放置——前者适合大多数训练场景,后者只在特殊调试或细粒度控制时才需要。
什么时候该用 MirroredStrategy?
它适用于单机多卡、同步数据并行训练,模型参数在每张卡上镜像复制,梯度通过 NCCL 或 HierarchicalCopy 合并。不是所有模型都自动适配:如果你的模型里有未被 tf.Variable 管理的状态(比如 Python list 存权重、tf.py_function 里改全局变量),MirroredStrategy 会静默失效或报 ValueError: Variable is not available in this strategy。
- 必须把模型构建、损失定义、优化器创建全放在
strategy.scope()内 -
tf.data.Dataset的batch()尺寸要设为全局 batch size(例如 8 卡 × 每卡 32 = 256) - 自定义训练循环中,
strategy.run()返回的是 PerReplica 对象,取均值要用strategy.reduce(tf.distribute.ReduceOp.SUM, ...)
tf.distribute.MirroredStrategy 的典型初始化陷阱
很多人直接写 strategy = tf.distribute.MirroredStrategy() 就跑,结果只用了 1 张卡——因为 TensorFlow 默认只识别 CUDA_VISIBLE_DEVICES 显式指定的设备。如果没设环境变量,它可能只看到 GPU:0。
- 启动前加
os.environ["CUDA_VISIBLE_DEVICES"] = "0,1,2,3"(顺序很重要,影响 NCCL ring 构建) - 检查实际可用设备:
strategy.num_replicas_in_sync应等于你期望的卡数 - 避免在
MirroredStrategy外创建任何tf.Variable,否则会报Not in scope - 使用
tf.config.list_physical_devices("GPU")确认驱动和 CUDA 版本兼容(TF 2.12 要求 CUDA 11.8+)
自定义训练步中如何正确聚合梯度?
strategy.run(train_step, args=(x, y)) 在每张卡上独立执行,返回的是各卡 loss 的集合,不是标量。直接 np.mean() 会出错,因为返回的是 PerReplica 类型。
@tf.function
def train_step(x, y):
with tf.GradientTape() as tape:
pred = model(x, training=True)
loss = loss_fn(y, pred)
grads = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
return loss
<h1>正确聚合方式:</h1><p>per_replica_loss = strategy.run(train_step, args=(x, y))
loss = strategy.reduce(tf.distribute.ReduceOp.MEAN, per_replica_loss, axis=None)</p>
注意:ReduceOp.MEAN 是对所有副本 loss 取平均;若用 SUM,需再除以 strategy.num_replicas_in_sync 才等价于全局平均。
为什么验证/预测阶段容易显存爆炸?
MirroredStrategy 下,model.predict() 或 model.evaluate() 默认仍走多卡路径,但验证数据通常不 shuffle、不重复,导致各卡分到的数据量不均,某张卡先跑完就空等,其余卡显存持续占满。
- 验证时显式切换到单卡:
with strategy.scope():内不做 predict,改用strategy.experimental_distribute_dataset(val_ds)+ 手动strategy.run(eval_step) - 更稳妥的做法:验证阶段用
tf.distribute.get_strategy()(即默认策略),绕过 MirroredStrategy - 如果用 Keras
model.fit(),确保validation_data是tf.data.Dataset,且已调用cache().prefetch(),否则 IO 成瓶颈,掩盖 GPU 利用率问题
多卡最隐蔽的问题不在代码写法,而在 NCCL 初始化失败时 TensorFlow 往往只打一条 INFO 日志(如 NCCL version 2.14.2),然后悄悄退化成单卡——务必检查 strategy.num_replicas_in_sync 和 nvidia-smi 的 GPU 利用率是否匹配。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











