You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras预测方法结果不一致:GPU与CPU运行差异问询

Keras预测方法在GPU与CPU上的结果差异问题

问题说明

原本认为Keras的predict()、predict_on_batch()、predict_step()以及直接调用模型(model(x, training=False)即__call__())这四种方法输出结果应该完全一致,仅批量处理效率有区别。但在图像超分辨率任务中,P100 GPU上predict()/predict_on_batch()与predict_step()/__call__()结果差异明显,CPU上四种方法结果则完全一致。

测试代码

for lowres, _ in val.take(1):
    # 随机裁剪低分辨率图像用于超分
    lowres = tf.image.random_crop(lowres, (150, 150, 3))  # uint8
    
    # 添加批量维度
    model_inputs = tf.expand_dims(lowres, axis=0)  # (1, 150, 150, 3), uint8
    
    # 转换为float32类型输入模型
    model_inputs = tf.cast(model_inputs, tf.float32)  # float32
    
    preds = model.predict_on_batch(model_inputs)
    min_val = tf.reduce_min(preds).numpy()
    max_val = tf.reduce_max(preds).numpy()
    print("Min value: ", min_val)
    print("Max value: ", max_val)
    
    preds = model.predict(model_inputs)
    min_val = tf.reduce_min(preds).numpy()
    max_val = tf.reduce_max(preds).numpy()
    print("Min value: ", min_val)
    print("Max value: ", max_val)
    
    preds = model.predict_step(model_inputs)
    min_val = tf.reduce_min(preds).numpy()
    max_val = tf.reduce_max(preds).numpy()
    print("Min value: ", min_val)
    print("Max value: ", max_val)
    
    preds = model(model_inputs, training=False)  # __call__()
    min_val = tf.reduce_min(preds).numpy()
    max_val = tf.reduce_max(preds).numpy()
    print("Min value: ", min_val)
    print("Max value: ", max_val)

输出结果

Min value:  -6003.622
Max value:  5802.6826

Min value:  -6003.622
Max value:  5802.6826

Min value:  -53.7696
Max value:  315.1499

Min value:  -53.7696
Max value:  315.1499

模型详情

模型仅包含Conv2D、Add、tf.nn.depth_to_space(像素洗牌)和Rescaling层,无BatchNorm或Dropout这类依赖训练模式的层,未使用子类化或重写方法,仅通过keras.Model(inputs, outputs)构建。其中predict_step()和__call__()的输出符合预期。


差异原因

  1. 执行模式与图优化差异
    • predict()和predict_on_batch()默认触发TensorFlow的静态图执行模式,GPU上会进行算子融合、精度优化等图转换操作;而predict_step()和直接调用__call__()默认使用动态图(Eager Execution)模式。两种模式下,部分算子的计算路径或精度处理可能不同,比如Rescaling层在静态图中可能被融合到卷积算子里,动态图中则单独执行,累积浮点误差被放大后导致结果偏差。
  2. GPU并行计算的异步特性
    • GPU的并行调度机制会让算子异步执行,predict()系列方法的内存分配、任务调度策略与动态图模式不同,硬件层面的浮点运算精度限制会进一步放大这种差异,而CPU的计算并行度低,误差不容易显现。
  3. 参数读取与张量存储差异
    • 静态图模式下会对模型参数的读取方式做优化,动态图则实时读取参数,虽然参数值本身一致,但GPU张量的存储和读取过程中可能存在细微的精度损失,累积后导致结果不同。

解决建议

  • 统一执行模式:用tf.function装饰predict_step或直接调用的逻辑,将动态图转为静态图;或者关闭predict()的图优化(通过设置相关配置),确保所有方法使用相同的执行路径。
  • 检查Rescaling层逻辑:确认归一化/缩放操作在所有模式下的计算逻辑完全一致,避免图优化改变计算顺序。
  • 提升浮点精度:尝试将模型计算切换为tf.float64类型,看差异是否缩小,验证是否由浮点精度累积导致。

内容的提问来源于stack exchange,提问作者while1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 01:37:04