tensorflow 在GPU上,tf.round将-0.5四舍五入为0.0而不是-0.0,

k2fxgqgv  于 4个月前  发布在  其他
关注(0)|答案(7)|浏览(53)

问题类型

Bug

来源

二进制文件

Tensorflow版本

2.10.0,以及nightly版本

自定义代码

是的

OS平台和发行版

Linux Ubuntu 20.04

移动设备

无响应

Python版本

3.7.15

Bazel版本

无响应

GCC/编译器版本

无响应

CUDA/cuDNN版本

11.3,8.2.4

GPU型号和内存

无响应

当前行为?

np.roundtf.round在CPU上将-0.5四舍五入为-0.0,但GPU上的tf.round四舍五入为0.0

重现问题的独立代码

print("numpy", np.round([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]))
with tf.device("/cpu:0"):
    print("CPU", tf.round([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]))
with tf.device("/gpu:0"):
    print("GPU", tf.round([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]))

相关日志输出

numpy [-2. -2. -0.  0.  2.  2.]
CPU tf.Tensor([-2. -2. -0.  0.  2.  2.], shape=(6,), dtype=float32)
GPU tf.Tensor([-2. -2.  0.  0.  2.  2.], shape=(6,), dtype=float32)
cnh2zyt3

cnh2zyt31#

@reedwm 我猜这是在GPU上生成的MLIR。当它们是MLIR生成时,很难在完整路径中详细跟踪这些OPS。你有什么提示来加速排错吗?
检查我的colab:
https://colab.research.google.com/gist/bhack/ad0d1f3be6d3b930b118fa878c9332eb/untitled195.ipynb
我猜这是因为我认为MLIR使用了LLVM的四舍五入到最接近的偶数模式,但很难完全跟踪下沉。
另外,正如@creakseek 所说,它将打开许多GPU/CPU不匹配的问题,有没有更好的方法来系统地解决这些问题?

cbjzeqam

cbjzeqam2#

@reedwm 我猜这是在GPU上生成的MLIR。当它们是MLIR生成时,很难在完整路径中详细跟踪这些OPS。你有什么提示来加速排错吗?

很遗憾,我对MLIR生成的内核的工作方式不太熟悉。@frgossen,你能在这里发表评论吗?

查看我的colab:
https://colab.research.google.com/gist/bhack/ad0d1f3be6d3b930b118fa878c9332eb/untitled195.ipynb
我想这是因为我认为MLIR使用了LLVM的四舍五入到最接近的偶数模式,但很难完全跟踪下沉。
有趣的是,所以看起来TF匹配了__float2int_rn的行为。__float2int_rn在给定-0.5时错误地给出了正零。@nluehr这是CUDA的bug还是预期行为?
另外,正如@creakseek所说,它将打开许多GPU/CPU不一致的问题,有没有更好的方法来系统地处理这些问题?
我认为分开开问题是可以的。

fzsnzjdm

fzsnzjdm3#

这是CUDA的bug还是预期行为?

MLIR中实现完全跟踪降低过程的难点在于...但是,如果它确实降低到了__float2int_rn,我认为-0是预期的结果。请参阅C++版本:

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    cout << nearbyint( -0.5f ) * 2.0f << endl;
}

我认为单独开个问题是可以的。

好的,但我们确实需要找到一种更简单的方法来跟踪这些代码路径,以便进行高效的排期。

tvz2xvvm

tvz2xvvm4#

如果真的降低到__float2int_rn,我认为0是预期的结果。请参阅C++版本
您向nearbyint传递了一个正数。如果您传递了一个负数,它将打印-0而不是0。
好的,但我们确实需要找到一种更简单的方法来跟踪这些代码路径,以便进行高效的分类。
@poulsbo 你觉得在这里打开一个跟踪GitHub问题是否合适,以跟踪CPU和GPU之间的差异?

ax6ht2ek

ax6ht2ek5#

你向nearbyint传递了一个正数。如果你传递了一个负数,它会打印-0而不是0。
是的,谢谢。我修正了拼写错误。我想c++ gist应该能正确表示__float2int_rn

but5z9lq

but5z9lq6#

在LLVM NVPTX目标降低源代码中,我找到了:

// This is the the rounding method used in CUDA libdevice in C like code:
// float roundf(float A)
// {
//   float RoundedA = (float) (int) ( A > 0 ? (A + 0.5f) : (A - 0.5f));
//   RoundedA = abs(A) > 0x1.0p23 ? A : RoundedA;
//   return abs(A) < 0.5 ? (float)(int)A : RoundedA;
// }

但是它给了我 -1

#include <iostream>

using namespace std;
// This is the the rounding method used in CUDA libdevice in C like code:
float roundf(float A)
{
   float RoundedA = (float) (int) ( A > 0 ? (A + 0.5f) : (A - 0.5f));
   RoundedA = abs(A) > 0x1.0p23 ? A : RoundedA;
   return abs(A) < 0.5 ? (float)(int)A : RoundedA;
}

int main()
{
  cout << roundf(-0.5f) << endl;
}
xqnpmsa8

xqnpmsa87#

好的,这个匹配CUDA roundf。我仍然没有找到确切的代码路径,我们正在降低什么。

相关问题