凭什么 batch size 都是2的幂数?

共 4059字,需浏览 9分钟

 ·

2022-07-22 12:23

转自:新智元

你有没有疑惑过,为啥batch size都是2的幂数?

 

有人觉得是「习惯」,也有人说这算是一种约定俗成的标准,因为从「计算」的角度来看,batch size为2的幂数有助于提高训练效率。

 

 

但计算机科学就是一门实践的学科,理论再完美也需要实验结果来验证。

 

最近一位AI研究者Sebastian动手试了一下所有的batch size,结果发现其对性能的影响微乎其微,甚至在某些情况下,不使用2的幂数训练速度更快

 

 

实验结果一出,也得到大量网友的响应。

 

有网友认为,使用2的幂数单纯是出于审美上的愉悦,但我并不觉得有什么区别。有时候为了体验「游走于刀尖上」的感觉,我就用10的倍数。

 

也有网友认为batch size的设置存在玄学,他有时候还会用7的倍数。

 

 

更叛逆的网友表示,我用2的幂数,但是幂数带「小数」

 

 

不过也有正经点的讨论,认为作者做的基准测试可能是精度不够的,比如batch size选择512和539的区别可能根本测量不出来。

 

 

也有人表达反对意见,我们「不是必须」选择2的幂数,但我们「应该」这样做。

 

首先这个基准测试毫无意义,在一个超级小数据集上使用一个超小网络进行实验,我们无法从这样的玩具数据中获得任何现实世界的指标。

 

其次,在TPU上选择batch size为8的倍数太大了,数据将被填充,并且会浪费大量的计算。

 

我认为即使在GPU上,padding也会有影响,可能会留下潜在的性能改进空间。

 

 

理论基础

 

在看实践基准结果之前,我们简单回顾一下选择batch size为2的幂的主要思路。

 

内存对齐(Memory Alignment)

 

选择batch size为 2 的幂的主要论据之一是 CPU 和 GPU 内存架构是以 2 的幂进行组织的。或者更准确地说,存在内存页的概念,它本质上是一个连续的内存块。

 

如果你使用的是 macOS 或 Linux,就可以通过在终端中执行 getconf PAGESIZE 来检查页面大小,它应该会返回一个 2 的幂的数字。

 

其目的是将一个或多个batch整齐地放在一个Page上,以帮助在GPU中进行并行处理,所以batch size大小为2的幂数可以帮助获得更好的内存排列。这与在视频游戏开发和图形设计中使用OpenGL和DirectX时选择2次方纹理相类似。

 

矩阵乘法和Tensor Core

 

英伟达有一个矩阵乘法背景用户指南,解释了矩阵维度和GPU的计算效率之间的关系。

 

文章中建议不要选择矩阵尺寸为2的幂,而是选择矩阵尺寸为8的倍数,以便在带有Tensor Core的GPU上进行混合精度训练。当然,这两者之间是有重叠的,比如8, 16, 32等。

 

 

为什么会是 8 的倍数?这与矩阵乘法有关。

 

假设我们在矩阵 A 和 B 之间有以下矩阵乘法:

 

 

计算两个矩阵 A 和 B 相乘的一种方法是计算矩阵 A 的行向量和矩阵 B 的列向量之间的点积(dot product)。

 

 

每个点积由一个「加法」和一个「乘法」操作组成,需要得到 M×N 个这样的点积,因此共有 2×M×N×K 次浮点运算(FLOPS)。

 

不过现在矩阵在 GPU 上的乘法并不完全如此,GPU 上的矩阵乘法还包括tiling

 

 

如果使用带有 Tensor Cores 的 GPU,例如英伟达 V100,当矩阵维度 (M、N 和 K)与 16 字节的倍数对齐后,在 FP16 混合精度训练的情况下,8 的倍数对于计算效率来说是最佳的。

 

通常维度 K 和 N 由神经网络架构决定,但batch size(此处为 M)通常是由开发者控制的。

 

因此,假设batch size为 8 的倍数在理论上对于具有 Tensor Core 和 FP16 混合精度训练的 GPU 来说是最有效的,不过实际提升效果有多少,还需要做过实验才知道。

 

简单的Benchmark

 

为了了解不同的batch size对实际训练的影响,作者在CIFAR-10上运行了一个简单的基准训练MobileNetV3(large)的10个epoch,图像被调整为224×224以达到适当的GPU利用率。

 

在V100卡上运行了16位原生自动混合精度训练,这样可以更有效地利用GPU的Tensor Cores。

 

代码链接:https://github.com/rasbt/b3-basic-batchsize-benchmark

 

小batch size

 

从batch size为128的小基准开始,Train Time对应于在 CIFAR-10 上训练 MobileNetV3 的 10 个 epoch,Inference Time为在测试集中的 10k 图像上评估模型。

 

 

如果把batch size为128作为基准点,减少一个批处理量(127)或增加一个批处理量(129)确实会导致训练性能稍慢。然而,这里的差异几乎不明显,我认为它可以忽略不计。

 

将批处理量减少28(即100)会导致更明显的性能减慢。这可能是因为模型现在需要处理比以前更多的批次(50,000/100=500 vs. 50,000/100=390)。

 

可能由于类似的原因,当我们将批次大小增加28(156)时,我们可以观察到训练时间更短了。

 

最大的batch size

 

鉴于 MobileNetV3 架构和输入图像大小,128可能太小了,因此 GPU 利用率约为 70%。

 

为了研究 GPU 满负荷时的训练时间差异,作者将batch size增加到 512,以使 GPU 显示出接近 100% 的计算利用率。

 

 

由于 GPU 内存限制,batch size值无法超过 515。

 

同样,正如我们之前看到的,作为 2 的幂(或 8 的倍数)的批大小确实会产生很小但几乎不明显的差异。

 

多GPU训练

 

前两个基准测试评估了在单个GPU上的训练性能,转到多GPU上结果是否会有不同?

 

 

可以看到,这一次,2次方和8次方的批处理规模(256)并不比257快。

 

本处使用DistributedDataParallel(DDP)作为默认的多GPU训练策略。

 

注意事项

 

这里需要强调的是上述所有基准测试都有注意事项。例如只运行每个配置一次。理想情况下可能希望多次重复这些运行并报告平均值和标准偏差。

 

但最终结论可能都是一样的:即性能没有实质性差异

 

此外,虽然实验是在同一台机器上运行了所有基准测试,但是以连续的顺序运行测试,运行之间没有很长的等待时间。也就是说GPU的温度在运行时可能有所不同,并且可能会对计时产生轻微影响。

 

资源和讨论

 

Ross Wightman 曾提到,他也不认为选择batch size为 2 的幂会产生明显的差异,但选择 8 的倍数对于某些矩阵维度可能很重要。

 

此外 Wightman 指出,在使用 TPU 时batch size至关重要,不过作者表示他无法轻松地访问到 TPU,所以也就没做基准测试。

 

 

Rémi Coulom-Kayufu 曾经做过一个实验表明,2 次方的batch size实际上并非最佳选择。

 

对于卷积神经网络,可以通过以下方式计算出较好的值

 

 

其中,n 是整数,SM 是 GPU 内核的数量(例如,V100 为 80,RTX 2080 Ti 为 68)。

 

结论

 

基于本文分享的基准结果,我不相信选择batch size规模为2的幂或8的倍数在实践中会有明显的区别。

 

然而,在任何特定的项目中,不管是研究基准还是机器学习的实际应用,选择2次方(即64、128、256、512、1024等)可以会更加直接和易于管理。

 

另外,如果你对发表学术研究论文感兴趣,将你的批次大小选择为2的幂,会使你的结果看起来不那么像「调参出来的」。

 

虽然坚持使用2次方的batch size可以帮助限制超参数搜索空间,但必须强调批量大小仍然是一个超参数。

 

 

有些人认为,较小的batch size有助于泛化性能,而另一些人则建议尽可能地增加批次大小。

 

就我个人而言,我发现最佳batch size高度依赖于神经网络架构和损失函数。例如,在最近一个使用相同ResNet架构的研究项目中,我发现最佳批次大小可以在16到256之间,完全取决于损失函数。

 

因此,我建议始终考虑将调整batch size作为你的超参数优化搜索的一部分。

 

如果由于内存的限制,你不能使用512的batch size,你也不必降到256,选择500也是完全可以的。


参考资料:
https://sebastianraschka.com/blog/2022/batch-size-2.html
https://www.reddit.com/r/MachineLearning/comments/vs1wox/p_no_we_dont_have_to_choose_batch_sizes_as_powers/


浏览 21
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报