【发布时间】:2022-01-11 12:41:04
【问题描述】:
我正在尝试找出 numpy/pytorch、gpu/cpu、float16/float32 数字之间的舍入差异,而我的发现让我感到困惑。
基本版是:
a = torch.rand(3, 4, dtype=torch.float32)
b = torch.rand(4, 5, dtype=torch.float32)
print(a.numpy()@b.numpy() - a@b)
结果如预期的那样全为零,但是
print((a.cuda()@b.cuda()).cpu() - a@b)
得到非零结果。 为什么 Pytorch float32 matmul 在 gpu 和 cpu 上的执行方式不同?
一个更令人困惑的实验涉及float16,如下:
a = torch.rand(3, 4, dtype=torch.float16)
b = torch.rand(4, 5, dtype=torch.float16)
print(a.numpy()@b.numpy() - a@b)
print((a.cuda()@b.cuda()).cpu() - a@b)
这两个结果都是非零的。 为什么numpy和torch处理float16数字的方式不同?我知道cpu只能做float32操作,numpy在计算前将float16转换为float32,但是torch计算也是在cpu上执行的。
你猜怎么着,print((a.cuda()@b.cuda()).cpu() - a.numpy()@b.numpy()) 得到一个全为零的结果!这对我来说纯粹是幻想......
环境如下:
- 蟒蛇:3.8.5
- 火炬:1.7.0
- numpy:1.21.2
- cuda:11.1
- GPU:GeForce RTX 3090
根据一些评论者的建议,我添加了以下相等测试
(a.numpy()@b.numpy() - (a@b).numpy()).any()
((a.cuda()@b.cuda()).cpu() - a@b).numpy().any()
(a.numpy()@b.numpy() - (a@b).numpy()).any()
((a.cuda()@b.cuda()).cpu() - a@b).numpy().any()
((a.cuda()@b.cuda()).cpu().numpy() - a.numpy()@b.numpy()).any()
分别直接跟上面五个打印函数,结果分别是:
False
True
True
True
False
而对于最后一个,我试了好几次,我想我可以排除运气。
【问题讨论】:
-
“非零结果”是什么意思?
-
据我所知,使用浮点类型获得可重现结果的唯一方法是使用严格模式,我不知道 Python 或这些库中的任何一个使用什么。您可以尝试将您的差异测试更改为等于测试以排除引入错误的减法,但我希望
x-x像您所做的那样无论模式如何都会变为0.0。 -
@talonmies 这意味着返回的张量的某些元素具有非零值,例如上面的第一个 print((a.cuda()@b.cuda()).cpu() - a@b) 返回:张量([[-1.6999e-04, 7.8678e-06, -1.6534e-04, -1.2589e-04, -1.5211e-04], [ 3.4809e-05, 1.1599e-04 , 9.6798e-05, 2.5213e-05, 1.9252e-05], [-1.6284e-04, 4.0352e-05, -2.1398e-04, -7.8559e-05, -2.4378e-04]])
-
@talonmies 而对于全零结果,我的意思是每个术语都有 0.0 的张量
-
它们代表什么是产品数量的相对误差?您确定零点不仅仅是表示问题。
np.all_zero和np.all_close是非常有用的工具,试试看你会得到什么