数值精度¶
在现代计算机中,浮点数使用 IEEE 754 标准表示。 有关浮点运算和 IEEE 754 标准的更多详细信息,请参阅浮点运算 特别要注意的是,浮点提供的精度有限(大约 7 位十进制数字 对于单精度浮点数,对于双精度,大约为 16 个十进制数字 浮点数),并且浮点加法和乘法不是 associative,因此操作的顺序会影响结果。 因此,PyTorch 无法得到保证 为浮点计算生成按位相同的结果,这些浮点计算是 数学上相同。同样,不能保证 PyTorch 版本、单个提交或不同平台。特别是 CPU 和 GPU 即使对于按位相同的输入,甚至在控制了 随机性的来源。
批处理计算或切片计算¶
PyTorch 中的许多操作都支持批量计算,其中执行相同的操作
对于输入批次的元素。这方面的一个例子是 and
。可以将批处理计算实现为批处理元素的循环,
并将必要的数学运算应用于各个 batch 元素,以提高效率
我们不会这样做,通常会对整个批次执行计算。数学
库,而 PyTorch 内部的操作实现可以生成
与非批处理计算相比,在这种情况下的结果略有不同。特别
let 和 是 3D 张量,其维度适合批量矩阵乘法。
then (批处理结果的第一个元素) 不能保证按位
identical to (输入批次的第一个元素的矩阵乘积)
尽管在数学上它是相同的计算。
A
B
(A@B)[0]
A[0]@B[0]
同样,应用于张量切片的操作不能保证产生以下结果
与应用于完整张量的相同操作的结果的切片相同。例如,设 为 2 维张量。 不保证按位等于 。A
A.sum(-1)[0]
A[:,0].sum()
极值¶
当输入包含较大的值,以至于中间结果可能会溢出 used 数据类型,则最终结果也可能溢出,即使它可以在原始 数据类型。例如:
import torch
a=torch.tensor([1e20, 1e20]) # fp32 type by default
a.norm() # produces tensor(inf)
a.double().norm() # produces tensor(1.4142e+20, dtype=torch.float64), representable in fp32
Nvidia Ampere 设备上的 TensorFloat-32(TF32)¶
在 Ampere Nvidia GPU 上,PyTorch 可以使用 TensorFloat32 (TF32) 来加速数学密集型运算,特别是矩阵乘法和卷积。
使用 TF32 张量核心执行操作时,仅读取输入尾数的前 10 位。
这可能会降低准确性并产生令人惊讶的结果(例如,将矩阵乘以单位矩阵可能会产生与输入不同的结果)。
默认情况下,TF32 张量核心对矩阵乘法处于禁用状态,而对卷积处于启用状态,尽管大多数神经网络工作负载在使用 TF32 时具有与使用 fp32 时相同的收敛行为。
如果您的网络不需要完整的 float32 精度,我们建议为矩阵乘法启用 TF32 张量核心。
如果您的网络需要矩阵乘法和卷积的全 float32 精度,则也可以使用 .torch.backends.cuda.matmul.allow_tf32 = True
torch.backends.cudnn.allow_tf32 = False
有关更多信息,请参阅 TensorFloat32。
FP16 GEMM 的精度降低¶
半精度 GEMM 操作通常以单精度进行中间累积(减少)来完成,以提高数值精度和提高对溢出的弹性。为了提高性能,某些 GPU 架构,尤其是较新的 GPU 架构,允许对中间累积结果进行一些截断,以降低精度(例如,半精度)。从模型收敛的角度来看,这种变化通常是良性的,尽管它可能会导致意外的结果(例如,最终结果应该以半精度表示的值)。
如果降低精度的缩减有问题,可以使用inf
torch.backends.cuda.matmul.allow_fp16_reduced_precision_reduction = False
AMD Instinct MI200 器件上的精度降低的 FP16 和 BF16 GEMM 和卷积¶
在 AMD Instinct MI200 GPU 上,FP16 和 BF16 V_DOT2和 MFMA 矩阵指令将输入和输出非正规值刷新为零。FP32 和 FP64 MFMA 矩阵指令不会将输入和输出非正规值刷新为零。受影响的指令仅由 rocBLAS (GEMM) 和 MIOpen (卷积) 内核使用;所有其他 PyTorch 操作都不会遇到此行为。所有其他受支持的 AMD GPU 都不会遇到此行为。
rocBLAS 和 MIOpen 为受影响的 FP16 操作提供替代实现。未提供 BF16 操作的替代实现;BF16 数的动态范围比 FP16 数大,并且不太可能遇到非正规值。对于 FP16 替代实现,FP16 输入值将强制转换为中间 BF16 值,然后在累积 FP32 操作后强制转换回 FP16 输出。这样,输入和输出类型将保持不变。
使用 FP16 精度进行训练时,某些模型可能无法收敛,FP16 非规范刷新为零。在梯度计算期间,非正规值更频繁地出现在训练的向后传递中。默认情况下,PyTorch 将在向后传递期间使用 rocBLAS 和 MIOpen 替代实现。可以使用环境变量 ROCBLAS_INTERNAL_FP16_ALT_IMPL 和 MIOPEN_DEBUG_CONVOLUTION_ATTRIB_FP16_ALT_IMPL 覆盖默认行为。这些环境变量的行为如下:
向前 |
向后 |
|
---|---|---|
环境未设置 |
源语言 |
互生 |
Env 设置为 1 |
互生 |
互生 |
Env 设置为 0 |
源语言 |
源语言 |
以下是可以使用 rocBLAS 的操作列表:
torch.addbmm
torch.addmm
Torch.baddbmm
Torch.bmm
torch.mm
torch.nn.GRUCell
torch.nn.LSTMCell
torch.nn.线性
torch.sparse.addmm
以下 torch._C._ConvBackend 实现:
慢Nd
slowNd_transposed
slowNd_dilated
slowNd_dilated_transposed
以下是可以使用 MIOpen 的操作列表:
torch.nn.Conv[转置]Nd
以下 torch._C._ConvBackend 实现:
ConvBackend::Miopen
ConvBackend::MiopenDepthwise
ConvBackend::MiopenTranspose