我们有一个在Tensorflow(1.10和1.3)中开发的对象检测模型,它使用标准的CNN和一些额外的层。 我们使用保存的模型格式在 Tensorflow Serve 1.13.0 中托管模型,在带有 Cuda 10 和 CUDNN 7.4.x 的 Nvidia Tesla V100 GPU 上(我们使用 Google 容器映像和/或 dockerfile 进行 Tensorflow 服务。
我们运行单元测试以确保预测结果符合我们的预期。 这些在 CPU 上都很好用。 但是当我们在上面的 GPU/CUDA/CUDNN 配置上运行它们时,我们得到的预测概率差异从 .001 到 .0005。
我们的目标是了解:
- 为什么会这样?
- 我们能做些什么来防止它?
- 如果我们可以做些什么来防止它,这是否需要某种权衡,例如性能?
我们尝试了以下实验:
-
使用批处理大小为 1 的检查点在张量流 GPU 上多次运行同一模型
- 结果相同
-
使用具有不同批次大小的检查点在 GPU 上多次运行同一模型
- 结果偏差 .001
-
使用具有不同批大小的检查点在 CPU 上多次运行同一模型
- 结果相同
-
使用批处理大小为 1 的检查点在张量流服务 GPU 上多次运行同一模型
- 结果相同
-
将带有检查点的运行与在 GPU 上使用已保存模型的运行进行比较
- 结果差 .005
-
将带有检查点的运行与在 CPU 上使用保存模型的运行进行比较
- 结果相同
-
尝试在 GPU 上更改batch_size和设置
TF_CUDNN_USE_AUTOTUNE=0
- 将最大差从 .001 降低到 .0005
-
尝试添加
结果intra_op_parallelism_threads=1
,inter_op_parallelism_threads=1
与TF_CUDNN_USE_AUTOTUNE=0
一起使用时没有任何区别- 与上述结果无异
总结:在 GPU 上运行推理的结果有几种情况不同:
- 使用检查点与保存的模型。
- 批量大小 = 1 与各种批量大小
- 设置
TF_CUDNN_USE_AUTOTUNE=0
可减少使用各种批量大小时的差异
TF 1.10 和 1.13.1 会发生这种情况
同样,我们的目标是了解:
- 为什么会这样?
- 我们能做些什么来防止它?
- 如果我们可以做些什么来防止它,这是否需要某种权衡,例如性能?
我有一些疯狂的非确定性事情正在发生,这些事情没有发生在笔记本电脑的 GPU 中,而是发生在服务器的 GPU 中。
解决方案:现在我每次调用 cublas、cusolver 等后都会调用cudaDeviceSynchronize()
,功能,并且不确定的问题消失了! :)这让我非常疯狂和愤怒,但不幸的是,因为这些库使用流,然后你可以在这些库的函数完全写入结果之前结束使用设备指针的内容。