浅谈混合精度训练imagenet 零、序 本文没有任何的原理和解读,只有一些实验的结论,对于想使用混合精度训练的同学可以直接参考结论白嫖,或者直接拿github上的代码(文末放送)。 二、混合精度训练 混合精度训练,以pytorch 1.6版本为基础的话,大致是有3种方案,依次介绍如下: 模型和输入输出直接half,如果有BN,那么BN计算需要转为FP32精度,我上面的问题就是基于此来训练的 四、不同混合精度训练方法对比 实验均在ResNet50和imagenet下面进行的,LR随着BS变换和线性增长,公式如下 实验结果 模型FP16+BNFP32实验记录 模型数据集batchsize(所有卡的总数 Apex混合精度实验记录 模型MODE数据集batchsize(所有卡的总数)优化器LearningRatetop1@accResNet50O1(FP16训练,部分op,layer用FP32计算)ImageNet1k4096SGD O1的精度。
GitHub 仓库地址:https://github.com/yanqiangmiffy/amp-pytorch Pytorch自动混合精度训练模板 使用 pytorch 的自动混合精度教程 Adam + Cosine Learning rate scheduling with warmup 运行命令 python main.py --checkpoint_name baseline 3 混合精度训练 未使用混合精度训练: for batch_idx, (inputs, labels) in enumerate(data_loader): self.optimizer.zero_grad() self.model(inputs) loss = self.criterion(outputs, labels) loss.backward() self.optimizer.step() 使用混合精度训练
1. 1 首先实例化 torch.cuda.amp.autocast(enable=True) 作为上下文管理器或者装饰器,从而使脚本使用混合精度运行。 torch.nn.CrossEntropyLoss().cuda() # 定义优化器 opt = torch.optim.SGD(net.parameters(), lr=0.001) # 是否使用混合精度训练 set_to_none=True here can modestly improve performance end_timer_and_print("Mixed precision:") 02 混合精度测试 从实验2.1和2.2中,可以发现在batch size=40的情况下,不使用混合精度时,GPU内存占用为7011MB,运行时间为47.55 s。 而使用混合精度时,GPU内存占用为4997MB,运行时间为27.006 s。在当前运行配置中,内存占用节省了约28.73%,运行时间节省了约43.21%。
Tensor Core不是简单降低精度 9. 实验结论 从 cuBLAS SGEMM 到 Tensor Core GEMM,探索现代 GPU 矩阵计算的核心优化路径。 1. Tensor Core + Mixed Precision 例如: Transformer Linear 层 Attention Projection MLP CNN 卷积 大量采用 FP16/BF16 混合精度计算 Tensor Core不是简单降低精度 很多人认为: FP16 = 精度差 实际上: Tensor Core 混合精度: 输入: FP16 计算: FP32 accumulate 输出: FP32 实验结论 本次 Tesla T4 实验得到: Tensor Core 显著提高 GEMM 性能 矩阵越大,Tensor Core优势越明显 混合精度是AI推理的重要优化 CUDA Kernel 可以让我们理解 对于深度学习推理和训练,合理使用 FP16/BF16 混合精度,是获得高吞吐的重要手段。
AI编辑:我是小将 混合精度训练(mixed precision training)可以让模型训练在尽量不降低性能的情形下提升训练速度,而且也可以降低显卡使用内存。 目前主流的深度学习框架都开始支持混合精度训练。对于PyTorch,混合精度训练还主要是采用NVIDIA开源的apex库。 但是,PyTorch将迎来重大更新,那就是提供内部支持的混合精度训练,而且是自动混合精度训练: ? torch.cuda.amp.GradScaler : 对梯度进行scale来加快模型收敛,因为float16梯度容易出现underflow(梯度过小) 两者结合在一起,可以实现自动混合精度训练: # scaler.update() 当然,混合精度训练肯定要支持分布式训练,由于autocast是thread local的,所以要注意以下不同的情形: 如果使用torch.nn.DataParallel
HAWQ:基于 Hessian 的混合精度神经网络量化 本文为 UC Berkeley 大学发表在 ICCV 2019上的混合精度量化论文。 但是,将模型统一量化为超低精度会导致精度显着下降。一种新颖的解决方案是使用混合精度量化,因为与其他层相比,网络的某些部分可能允许较低的精度。但是,没有系统的方法来确定不同层的精度。 对于深度网络,蛮力方法不可行,因为混合精度的搜索空间在层数上是指数级的。另一个挑战是在将模型量化到目标精度时用于确定逐块微调顺序复杂度是阶乘级别的。 解决此问题的一种可能方法是使用混合精度量化,其中较高的精度用于网络的某些“敏感”层,而较低的精度用于“非敏感”层。但是,为每一层找到正确精度的搜索空间在层数上是指数级的。 Inception-V3 on ImageNet 消融实验 海森混合精度量化的有效性 ? 海森混合精度量化消融实验 Block-Wise微调的有效性 ? Block-Wise微调消融实验 ? ?
PyTorch分布式训练工作原理:分布式数据并行与混合精度训练导入与数据加载import torchimport torchvisionimport torchvision.transforms as is_main_process(): torch.save(*args, **kwargs)def is_main_process(): return get_rank() == 0混合精度训练混合精度结合了 GPU19.1DistributedDataParallel 2 GPU9.8DistributedDataParallel 4 GPU6.1DistributedDataParallel 4 GPU + 混合精度 混合精度训练通常能提供显著的加速,但在A100 GPU和其他基于Ampere的GPU架构上增益有限。
除此之外,nn.DataParallel 需要所有的GPU都在一个节点(一台机器)上,且并不支持 Apex 的 混合精度训练. 3. 另外,本文还演示了如何使用Apex进行简单的混合精度分布式训练。 使用Apex进行混合混合精度训练 混合精度训练,即组合浮点数 (FP32)和半精度浮点数 (FP16)进行训练,允许我们使用更大的batchsize,并利用NVIDIA张量核进行更快的计算。 opt_level 从 O0 (全部使用浮点数)一直到 O3 (全部使用半精度浮点数)。而 O1 和 O2 属于不同的混合精度程度,具体可以参阅APEX的官方文档。注意之前数字前面的是大写字母O。 Line37-38:混合精度训练需要缩放损失函数以阻止梯度出现下溢。不过Apex会自动进行这些工作。 这个脚本和之前的分布式训练脚本的运行方式相同。
混合精度在计算方法中结合了不同的数值精度。 使用精度低于FP32的系统可以减少内存使用,允许部署更大的网络。 数据传输需要更少的时间,而且计算性能会提高,尤其是在NVIDIA gpu上,它的Tensor Core支持这种精度。 DNNs的混合精度训练实现了两个主要目标: -减少需要的内存,使训练更大的模型或训练更大的小批量 -通过低精度算法降低所需资源,缩短训练/推理时间。 ? 本视频演示了如何在TensorFlow里训练ResNet-50与混合精度。 在这个视频中有五件重要的事情: 混合精度训练可以提高计算性能,并在保持训练精度的同时减少内存带宽。 NVIDIA官网关于混合精度的文档: ?
混合精度训练:只看训练过程就够了 一句话说清楚混合精度训练 在训练时,用半精度(FP16)算得快,用单精度(FP32)存得稳,两者结合就是混合精度训练。 一、训练时发生了什么变化? FP32 FP32 FP32 FP32 (稳但慢) (稳但慢) (稳但慢) (稳但慢) (稳但慢) 混合精度训练(FP16+FP32): criterion(output, target) loss.backward() # 反向 optimizer.step() # 更新 # 启用混合精度后 可以大一点 批量大小 原来的 2倍左右 省下来的内存可以放更多数据 热身(Warmup) 必须用 前几个epoch慢慢提高学习率 示例: # 原来:batch_size=32, lr=0.001 # 混合精度后 前向计算(自动混合精度) with autocast(): output = model(data) loss = nn.CrossEntropyLoss
特别是其自动混合精度(Auto-Mixed Precision, AMP)功能,能够在保持模型精度的前提下显著提升计算性能。 自动混合精度技术原理与实现 自动混合精度是一种先进的数值计算优化技术,通过在训练和推理过程中动态选择合适的数据精度来提升计算效率。 自动混合精度系统会自动分析计算图中的每个算子,智能地将数据类型转换为最适合的低精度格式,从而实现计算性能的整体优化。 训练循环的核心在于正确实现自动混合精度的前向传播和反向传播过程。 实验结果表明,通过Intel Extension for PyTorch实现的自动混合精度优化能够在保持模型精度的前提下显著提升训练和推理性能。
混合精度在计算方法中结合了不同的数值精度。NVIDIA Volta架构和Turing架构的GPU引入了TensorCore,它在单精度数学管道上提供了显著的吞吐量加速。 通过将梯度张量和激活张量上的存储需求和内存流量减半,可以以较低的精度对深度学习网络进行训练,以实现高吞吐量。以下Nvidia工具可以让您分析您的模型是否最大限度地利用TensorCore。
二、混合精度优化策略 (一)FP8混合精度训练框架 混合精度优化是DeepSeek在训练过程中采用的另一种重要策略。 通过灵活使用不同精度的数据格式,混合精度优化能够在保持模型性能的同时,显著提升计算效率和资源利用率。 DeepSeek采用了FP8混合精度训练框架。 为了平衡计算效率和模型性能,DeepSeek在混合精度优化中采用了关键操作保留高精度的策略。 这样可以确保注意力权重的计算结果具有较高的精度,从而提高模型的输出质量。 (三)精细量化策略 在混合精度优化中,量化是另一个关键环节。 此外,混合精度优化通过使用低精度数据格式,进一步提高了计算效率。这种优化使得DeepSeek能够在有限的硬件资源下,实现更高的模型容量。
降低计算精度是比较直接的方法。2017 年以来,fp16 混合精度技术 [2] 获得了广泛应用。在对模型效果无损的前提下,将模型训练和推理的速度提升了 50% 以上。 而为了维持模型效果,更低精度的方法(例如 int8)通常需要使用如下传统方案: 首先使用 fp16 混合精度将模型训练至收敛; 然后在模型计算密集型算子的权重、输入和输出位置处,插入伪量化结点,进行量化感知训练 由于目前流行的深度学习框架不支持 int8 精度,所以量化感知训练需要插入 fp16 的伪量化结点来模拟 int8 量化,导致量化感知训练反而比 fp16 混合精度训练慢 2-3 倍。 最后多机训练的瓶颈主要在梯度的通信,将梯度量化为 int8 精度可以大大加快分布式训练的速度。 量化原理 为了弥补量化带来的精度损失,通常需要用量化感知训练来模拟量化过程。 (附论文下载) CVPR21小样本检测:蒸馏&上下文助力小样本检测(代码已开源) 半监督辅助目标检测:自训练+数据增强提升精度(附源码下载) 目标检测干货 | 多级特征重复使用大幅度提升检测精度(
降低计算精度是比较直接的方法。2017 年以来,fp16 混合精度技术 [2] 获得了广泛应用。在对模型效果无损的前提下,将模型训练和推理的速度提升了 50% 以上。 而为了维持模型效果,更低精度的方法(例如 int8)通常需要使用如下传统方案: 首先使用 fp16 混合精度将模型训练至收敛; 然后在模型计算密集型算子的权重、输入和输出位置处,插入伪量化结点,进行量化感知训练 由于目前流行的深度学习框架不支持 int8 精度,所以量化感知训练需要插入 fp16 的伪量化结点来模拟 int8 量化,导致量化感知训练反而比 fp16 混合精度训练慢 2-3 倍。 最后多机训练的瓶颈主要在梯度的通信,将梯度量化为 int8 精度可以大大加快分布式训练的速度。 量化原理 为了弥补量化带来的精度损失,通常需要用量化感知训练来模拟量化过程。 如果直接按照离群值的范围来量化矩阵,会影响到量化后的精度,所以需要先对矩阵进行数值截断。
计算机表示浮点数有多种精度,其中Float16和Float32最为常见,即 fp32: Sign(1bit) + Range(8 bits) + Precision(23 bits) fp16: Sign (1bit) + Range(5 bits) + Precision(10 bits) GPU是一种专精浮点数运算的硬件设备,显然处理32位浮点数是处理16位浮点数计算量的2倍还多,在愿意损失一些精度的条件下使用 于是就有人提出了采用fp16来进行训练,具体而言在计算激活值和梯度的时候以fp16精度存储,执行优化算法的时候还原为fp32(缺失位补0),这样最终的效果是模型在GPU上以fp16和fp32两种方式加载 ,这被称为混合精度训练(mixed precision training),这种方式占用了更少的显存(全精度需要保存2份原始模型,混合精度保存1份原始模型,1份半精度模型,是原始模型的1.5倍),也加速了训练过程 ,即精度损失换时间。
常用的浮点数有双精度和单精度。除此之外,还有一种叫半精度的东东。 双精度64位,单精度32位,半精度自然是16位了。 半精度是英伟达在2002年搞出来的,双精度和单精度是为了计算,而半精度更多是为了降低数据传输和存储成本。 很多场景对于精度要求也没那么高,例如分布式深度学习里面,如果用半精度的话,比起单精度来可以节省一半传输成本。考虑到深度学习的模型可能会有几亿个参数,使用半精度传输还是非常有价值的。 比较下几种浮点数的layout: 双精度浮点数: ? 单精度浮点数: ? 半精度浮点数: ? 它们都分成3部分,符号位,指数和尾数。 不同精度只不过是指数位和尾数位的长度不一样。
基于此观察,作者提出了一种新的混合深度卷积(Mixed Depthwise Convolution, MDConv),它自然地在单个卷积中混合了多个内核大小。 如预期的那样,更大的卷积核大小会使用更多参数显著增加模型大小;当卷积核大小从3x3上升到7x7时,模型精度也跟着提升,但是当卷积核尺寸大于9x9时,模型精度会迅速下降,这表明较大的卷积核尺寸可能会损害精度和性能 基于此观察,本文提出了一种混合深度卷积(MDConv),它在单个卷积运算中混合了不同的卷积核大小,因此它可以轻松捕获具有各种分辨率的不同模式。 方法 MDConv的主要思想是在一个深度卷积运算中混合多个具有不同大小的卷积核,以便可以轻松地从输入图像中捕获不同类型的模式。 为了解决这个问题,作者提出了MDConv,它在单个操作中混合了多个卷积核以利用不同的卷积核大小。
机器之心报道 作者:力元 多数 PyTorch 高级库都支持分布式训练和混合精度训练,但是它们引入的抽象化往往需要用户学习新的 API 来定制训练循环。 用户可以通过将 cpu = True 或 fp16 = True 传递给此 init 来强制进行 CPU 训练或混合精度训练。这两个选项都可以使用脚本的启动器进行设置。 优化器 优化器也包装于一个为使混合精度训练运转执行必要操作的特殊容器里。如果状态 dict 是非空的或从检查点加载的,它会准确地处理状态 dict 的设备放置。 accelerator.backward(loss) 此行代码为向后传递添加了必要的步骤来提高混合精度,但对于其他集成则需要进行一些自定义。
机器之心报道 作者:力元 多数 PyTorch 高级库都支持分布式训练和混合精度训练,但是它们引入的抽象化往往需要用户学习新的 API 来定制训练循环。 用户可以通过将 cpu = True 或 fp16 = True 传递给此 init 来强制进行 CPU 训练或混合精度训练。这两个选项都可以使用脚本的启动器进行设置。 优化器 优化器也包装于一个为使混合精度训练运转执行必要操作的特殊容器里。如果状态 dict 是非空的或从检查点加载的,它会准确地处理状态 dict 的设备放置。 accelerator.backward(loss) 此行代码为向后传递添加了必要的步骤来提高混合精度,但对于其他集成则需要进行一些自定义。