Relative error greater than unit roundoff for torch.float16

Converting a data type from torch.float64 to torch.float16 often results in a relative error greater than the unit roundoff. Here’s a sample reproduction code

num_exps = 100000
urd = torch.tensor(torch.finfo(torch.float16).eps / 2.0, dtype=torch.float64) # Unit roundoff for FP16
rel_error = torch.zeros(num_exps, dtype = torch.float64)

for ii in range(num_exps):
val = torch.randn(1, dtype=torch.float64)
val_half = val.to(dtype=torch.float16)
rel_error[ii] = torch.abs((val - val_half) / val)

if torch.max(rel_error) > urd:
print(‘Max rel error :{} exceeded the urd : {}’.format(torch.max(rel_error), urd))
fig, axs = plt.subplots()
axs.hist(rel_error.numpy(), bins=100, label=‘$\delta$’, density=True)
axs.axvline(urd, color=‘red’, label=‘$u$’)
axs.legend()
plt.show()

the dynamic range of fp16 is notorious bad to the point where we’ve had to swap to bf16 in a number of cases. I would assume that’s what you’re seeing.