憑什么 batch size 都是2的冪數(shù)?
你有沒有疑惑過(guò),為啥batch size都是2的冪數(shù)?
有人覺得是「習(xí)慣」,也有人說(shuō)這算是一種約定俗成的標(biāo)準(zhǔn),因?yàn)閺摹赣?jì)算」的角度來(lái)看,batch size為2的冪數(shù)有助于提高訓(xùn)練效率。

但計(jì)算機(jī)科學(xué)就是一門實(shí)踐的學(xué)科,理論再完美也需要實(shí)驗(yàn)結(jié)果來(lái)驗(yàn)證。
最近一位AI研究者Sebastian動(dòng)手試了一下所有的batch size,結(jié)果發(fā)現(xiàn)其對(duì)性能的影響微乎其微,甚至在某些情況下,不使用2的冪數(shù)訓(xùn)練速度更快!

實(shí)驗(yàn)結(jié)果一出,也得到大量網(wǎng)友的響應(yīng)。
有網(wǎng)友認(rèn)為,使用2的冪數(shù)單純是出于審美上的愉悅,但我并不覺得有什么區(qū)別。有時(shí)候?yàn)榱梭w驗(yàn)「游走于刀尖上」的感覺,我就用10的倍數(shù)。
也有網(wǎng)友認(rèn)為batch size的設(shè)置存在玄學(xué),他有時(shí)候還會(huì)用7的倍數(shù)。

更叛逆的網(wǎng)友表示,我用2的冪數(shù),但是冪數(shù)帶「小數(shù)」

不過(guò)也有正經(jīng)點(diǎn)的討論,認(rèn)為作者做的基準(zhǔn)測(cè)試可能是精度不夠的,比如batch size選擇512和539的區(qū)別可能根本測(cè)量不出來(lái)。

也有人表達(dá)反對(duì)意見,我們「不是必須」選擇2的冪數(shù),但我們「應(yīng)該」這樣做。
首先這個(gè)基準(zhǔn)測(cè)試毫無(wú)意義,在一個(gè)超級(jí)小數(shù)據(jù)集上使用一個(gè)超小網(wǎng)絡(luò)進(jìn)行實(shí)驗(yàn),我們無(wú)法從這樣的玩具數(shù)據(jù)中獲得任何現(xiàn)實(shí)世界的指標(biāo)。
其次,在TPU上選擇batch size為8的倍數(shù)太大了,數(shù)據(jù)將被填充,并且會(huì)浪費(fèi)大量的計(jì)算。
我認(rèn)為即使在GPU上,padding也會(huì)有影響,可能會(huì)留下潛在的性能改進(jìn)空間。

理論基礎(chǔ)
理論基礎(chǔ)
在看實(shí)踐基準(zhǔn)結(jié)果之前,我們簡(jiǎn)單回顧一下選擇batch size為2的冪的主要思路。
內(nèi)存對(duì)齊(Memory Alignment)
選擇batch size為 2 的冪的主要論據(jù)之一是 CPU 和 GPU 內(nèi)存架構(gòu)是以 2 的冪進(jìn)行組織的。或者更準(zhǔn)確地說(shuō),存在內(nèi)存頁(yè)的概念,它本質(zhì)上是一個(gè)連續(xù)的內(nèi)存塊。
如果你使用的是 macOS 或 Linux,就可以通過(guò)在終端中執(zhí)行 getconf PAGESIZE 來(lái)檢查頁(yè)面大小,它應(yīng)該會(huì)返回一個(gè) 2 的冪的數(shù)字。

其目的是將一個(gè)或多個(gè)batch整齊地放在一個(gè)Page上,以幫助在GPU中進(jìn)行并行處理,所以batch size大小為2的冪數(shù)可以幫助獲得更好的內(nèi)存排列。這與在視頻游戲開發(fā)和圖形設(shè)計(jì)中使用OpenGL和DirectX時(shí)選擇2次方紋理相類似。
矩陣乘法和Tensor Core
英偉達(dá)有一個(gè)矩陣乘法背景用戶指南,解釋了矩陣維度和GPU的計(jì)算效率之間的關(guān)系。
文章中建議不要選擇矩陣尺寸為2的冪,而是選擇矩陣尺寸為8的倍數(shù),以便在帶有Tensor Core的GPU上進(jìn)行混合精度訓(xùn)練。當(dāng)然,這兩者之間是有重疊的,比如8, 16, 32等。

為什么會(huì)是 8 的倍數(shù)?這與矩陣乘法有關(guān)。
假設(shè)我們?cè)诰仃?A 和 B 之間有以下矩陣乘法:

計(jì)算兩個(gè)矩陣 A 和 B 相乘的一種方法是計(jì)算矩陣 A 的行向量和矩陣 B 的列向量之間的點(diǎn)積(dot product)。

每個(gè)點(diǎn)積由一個(gè)「加法」和一個(gè)「乘法」操作組成,需要得到 M×N 個(gè)這樣的點(diǎn)積,因此共有 2×M×N×K 次浮點(diǎn)運(yùn)算(FLOPS)。
不過(guò)現(xiàn)在矩陣在 GPU 上的乘法并不完全如此,GPU 上的矩陣乘法還包括tiling

如果使用帶有 Tensor Cores 的 GPU,例如英偉達(dá) V100,當(dāng)矩陣維度 (M、N 和 K)與 16 字節(jié)的倍數(shù)對(duì)齊后,在 FP16 混合精度訓(xùn)練的情況下,8 的倍數(shù)對(duì)于計(jì)算效率來(lái)說(shuō)是最佳的。
通常維度 K 和 N 由神經(jīng)網(wǎng)絡(luò)架構(gòu)決定,但batch size(此處為 M)通常是由開發(fā)者控制的。
因此,假設(shè)batch size為 8 的倍數(shù)在理論上對(duì)于具有 Tensor Core 和 FP16 混合精度訓(xùn)練的 GPU 來(lái)說(shuō)是最有效的,不過(guò)實(shí)際提升效果有多少,還需要做過(guò)實(shí)驗(yàn)才知道。
簡(jiǎn)單的Benchmark
簡(jiǎn)單的Benchmark
為了了解不同的batch size對(duì)實(shí)際訓(xùn)練的影響,作者在CIFAR-10上運(yùn)行了一個(gè)簡(jiǎn)單的基準(zhǔn)訓(xùn)練MobileNetV3(large)的10個(gè)epoch,圖像被調(diào)整為224×224以達(dá)到適當(dāng)?shù)腉PU利用率。
在V100卡上運(yùn)行了16位原生自動(dòng)混合精度訓(xùn)練,這樣可以更有效地利用GPU的Tensor Cores。

代碼鏈接:https://github.com/rasbt/b3-basic-batchsize-benchmark
小batch size
從batch size為128的小基準(zhǔn)開始,Train Time對(duì)應(yīng)于在 CIFAR-10 上訓(xùn)練 MobileNetV3 的 10 個(gè) epoch,Inference Time為在測(cè)試集中的 10k 圖像上評(píng)估模型。

如果把batch size為128作為基準(zhǔn)點(diǎn),減少一個(gè)批處理量(127)或增加一個(gè)批處理量(129)確實(shí)會(huì)導(dǎo)致訓(xùn)練性能稍慢。然而,這里的差異幾乎不明顯,我認(rèn)為它可以忽略不計(jì)。
將批處理量減少28(即100)會(huì)導(dǎo)致更明顯的性能減慢。這可能是因?yàn)槟P同F(xiàn)在需要處理比以前更多的批次(50,000/100=500 vs. 50,000/100=390)。
可能由于類似的原因,當(dāng)我們將批次大小增加28(156)時(shí),我們可以觀察到訓(xùn)練時(shí)間更短了。
最大的batch size
鑒于 MobileNetV3 架構(gòu)和輸入圖像大小,128可能太小了,因此 GPU 利用率約為 70%。
為了研究 GPU 滿負(fù)荷時(shí)的訓(xùn)練時(shí)間差異,作者將batch size增加到 512,以使 GPU 顯示出接近 100% 的計(jì)算利用率。

由于 GPU 內(nèi)存限制,batch size值無(wú)法超過(guò) 515。
同樣,正如我們之前看到的,作為 2 的冪(或 8 的倍數(shù))的批大小確實(shí)會(huì)產(chǎn)生很小但幾乎不明顯的差異。
多GPU訓(xùn)練
前兩個(gè)基準(zhǔn)測(cè)試評(píng)估了在單個(gè)GPU上的訓(xùn)練性能,轉(zhuǎn)到多GPU上結(jié)果是否會(huì)有不同?

可以看到,這一次,2次方和8次方的批處理規(guī)模(256)并不比257快。
本處使用DistributedDataParallel(DDP)作為默認(rèn)的多GPU訓(xùn)練策略。
注意事項(xiàng)
這里需要強(qiáng)調(diào)的是上述所有基準(zhǔn)測(cè)試都有注意事項(xiàng)。例如只運(yùn)行每個(gè)配置一次。理想情況下可能希望多次重復(fù)這些運(yùn)行并報(bào)告平均值和標(biāo)準(zhǔn)偏差。
但最終結(jié)論可能都是一樣的:即性能沒有實(shí)質(zhì)性差異。
此外,雖然實(shí)驗(yàn)是在同一臺(tái)機(jī)器上運(yùn)行了所有基準(zhǔn)測(cè)試,但是以連續(xù)的順序運(yùn)行測(cè)試,運(yùn)行之間沒有很長(zhǎng)的等待時(shí)間。也就是說(shuō)GPU的溫度在運(yùn)行時(shí)可能有所不同,并且可能會(huì)對(duì)計(jì)時(shí)產(chǎn)生輕微影響。
資源和討論
Ross Wightman 曾提到,他也不認(rèn)為選擇batch size為 2 的冪會(huì)產(chǎn)生明顯的差異,但選擇 8 的倍數(shù)對(duì)于某些矩陣維度可能很重要。
此外 Wightman 指出,在使用 TPU 時(shí)batch size至關(guān)重要,不過(guò)作者表示他無(wú)法輕松地訪問(wèn)到 TPU,所以也就沒做基準(zhǔn)測(cè)試。

Rémi Coulom-Kayufu 曾經(jīng)做過(guò)一個(gè)實(shí)驗(yàn)表明,2 次方的batch size實(shí)際上并非最佳選擇。
對(duì)于卷積神經(jīng)網(wǎng)絡(luò),可以通過(guò)以下方式計(jì)算出較好的值

其中,n 是整數(shù),SM 是 GPU 內(nèi)核的數(shù)量(例如,V100 為 80,RTX 2080 Ti 為 68)。
結(jié)論
結(jié)論
基于本文分享的基準(zhǔn)結(jié)果,我不相信選擇batch size規(guī)模為2的冪或8的倍數(shù)在實(shí)踐中會(huì)有明顯的區(qū)別。
然而,在任何特定的項(xiàng)目中,不管是研究基準(zhǔn)還是機(jī)器學(xué)習(xí)的實(shí)際應(yīng)用,選擇2次方(即64、128、256、512、1024等)可以會(huì)更加直接和易于管理。
另外,如果你對(duì)發(fā)表學(xué)術(shù)研究論文感興趣,將你的批次大小選擇為2的冪,會(huì)使你的結(jié)果看起來(lái)不那么像「調(diào)參出來(lái)的」。
雖然堅(jiān)持使用2次方的batch size可以幫助限制超參數(shù)搜索空間,但必須強(qiáng)調(diào)批量大小仍然是一個(gè)超參數(shù)。

有些人認(rèn)為,較小的batch size有助于泛化性能,而另一些人則建議盡可能地增加批次大小。
就我個(gè)人而言,我發(fā)現(xiàn)最佳batch size高度依賴于神經(jīng)網(wǎng)絡(luò)架構(gòu)和損失函數(shù)。例如,在最近一個(gè)使用相同ResNet架構(gòu)的研究項(xiàng)目中,我發(fā)現(xiàn)最佳批次大小可以在16到256之間,完全取決于損失函數(shù)。
因此,我建議始終考慮將調(diào)整batch size作為你的超參數(shù)優(yōu)化搜索的一部分。
如果由于內(nèi)存的限制,你不能使用512的batch size,你也不必降到256,選擇500也是完全可以的。
