訓練集全是16x16,32x32之類的小圖,達到上千萬張,訓練時發現數據載入很慢很慢很慢!!!看了下CPU 內存 GPU使用情況,發現CPU使用率都跑到90%去了,GPU使用率卻較低


PyTorch提速

原始文檔:https://www.yuque.com/lart/ugkv9f/ugysgn

聲明:大部分內容來自知乎和其他博客的分享,這裡只作為一個收集羅列。歡迎給出更多建議。 知乎回答(歡迎點贊哦):搬運到了github上:https://github.com/lartpang/PyTorchTricks有喜歡的可以三連下,或者繼續補充哦!
  • pytorch dataloader數據載入佔用了大部分時間,各位大佬都是怎麼解決的? - 人民藝術家的回答 - 知乎 https://www.zhihu.com/question/307282137/answer/907835663
  • 使用pytorch時,訓練集數據太多達到上千萬張,Dataloader載入很慢怎麼辦? - 人民藝術家的回答 - 知乎 https://www.zhihu.com/question/356829360/answer/907832358

changelog

  • 2019年11月29日:更新一些模型設計技巧和推理加速的內容,補充了下apex的一個介紹鏈接, 另外刪了tfrecord,pytorch能用麼?這個我記得是不能,所以刪掉了(表示刪掉:&
  • 2019年11月30日:補充MAC的含義,補充ShuffleNetV2的論文鏈接
  • 2019年12月02日:之前說的pytorch不能用tfrecord,今天看到https://www.zhihu.com/question/358632497下的一個回答,漲姿勢了
  • 2019年12月23日:補充幾篇關於模型壓縮量化的科普性文章
  • 2020年2月7日: 從文章中摘錄了一點注意事項, 補充在了代碼層面小節
  • 2020年4月30日:
    • 添加了一個github的文檔備份
    • 補充了卷積層和BN層融合的介紹的鏈接
    • 另外這裡說明下,對於之前參考的很多朋友的文章和回答,沒有把鏈接和對應的內容提要關聯在一起,估計會導致一些朋友閱讀時相關的內容時的提問,無法問到原作者,這裡深感抱歉。
    • 調整部分內容,將內容盡量與參考鏈接相對應
  • 2020年5月18日:發現一個之前的錯誤:non_blocking=False的建議應該是non_blocking=True.

預處理提速

  • 盡量減少每次讀取數據時的預處理操作,可以考慮把一些固定的操作,例如 resize ,事先處理好保存下來,訓練的時候直接拿來用
  • Linux上將預處理搬到GPU上加速:
    • NVIDIA/DALI :https://github.com/NVIDIA/DALI

IO提速

使用更快的圖片處理

  • opencv 一般要比 PIL 要快
  • 對於 jpeg 讀取,可以嘗試 jpeg4py
  • bmp 圖(降低解碼時間)

小圖拼起來存放(降低讀取次數)

對於大規模的小文件讀取,建議轉成單獨的文件,可以選擇的格式可以考慮:TFRecord(Tensorflow)recordIO(recordIO)hdf5pthn5lmdb 等等(https://github.com/Lyken17/Efficient-PyTorch#data-loader)

  • TFRecord:https://github.com/vahidk/tfrecord
  • 藉助 lmdb 資料庫格式:
    • https://github.com/Fangyh09/Image2LMDB
    • https://blog.csdn.net/P_LarT/article/details/103208405
    • https://github.com/lartpang/PySODToolBox/blob/master/ForBigDataset/ImageFolder2LMDB.py

預讀取數據

  • 預讀取下一次迭代需要的數據

【參考】

  • 如何給你PyTorch裏的Dataloader打雞血 - MKFMIKU的文章 - 知乎 https://zhuanlan.zhihu.com/p/66145913
  • 給pytorch 讀取數據加速 - 體hi的文章 - 知乎 https://zhuanlan.zhihu.com/p/72956595

藉助內存

  • 直接載到內存裡面,或者把把內存映射成磁碟好了

【參考】

  • 參見 https://zhuanlan.zhihu.com/p/66145913 的評論中 @雨宮夏一 的評論

藉助固態

  • 把讀取速度慢的機械硬碟換成 NVME 固態吧~

【參考】

  • 如何給你PyTorch裏的Dataloader打雞血 - MKFMIKU的文章 - 知乎 https://zhuanlan.zhihu.com/p/66145913

訓練策略

低精度訓練

  • 在訓練中使用低精度(FP16 甚至 INT8 、二值網路、三值網路)表示取代原有精度(FP32)表示
  • NVIDIA/Apex
    • https://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/100135729
    • https://github.com/nvidia/apex

代碼層面

  • torch.backends.cudnn.benchmark = True
  • Do numpy-like operations on the GPU wherever you can
  • Free up memory using del
  • Avoid unnecessary transfer of data from the GPU
  • Use pinned memory, and use non_blocking=True to parallelize data transfer and GPU number crunching
    • 文檔:https://pytorch.org/docs/stable/nn.html#torch.nn.Module.to
    • 關於 non_blocking=True 的設定的一些介紹:Pytorch有什麼節省顯存的小技巧? - 陳瀚可的回答 - 知乎 https://www.zhihu.com/question/274635237/answer/756144739
  • 網路設計很重要,外加不要初始化任何用不到的變數,因為 PyTorch 的初始化和 forward 是分開的,他不會因為你不去使用,而不去初始化
  • 合適的num_worker : Pytorch 提速指南 - 雲夢的文章 - 知乎 https://zhuanlan.zhihu.com/p/39752167(這裡也包含了一些其他細節上的討論)

模型設計

來自 ShuffleNetV2 的結論:(內存訪問消耗時間,memory access cost 縮寫為 MAC

  • 卷積層輸入輸出通道一致:卷積層的輸入和輸出特徵通道數相等時 MAC 最小,此時模型速度最快
  • 減少卷積分組:過多的 group 操作會增大 MAC ,從而使模型速度變慢
  • 減少模型分支:模型中的分支數量越少,模型速度越快
  • 減少 element-wise 操作:element-wise 操作所帶來的時間消耗遠比在 FLOPs 上的體現的數值要多,因此要儘可能減少 element-wise 操作(depthwise convolution也具有低 FLOPs 、高 MAC 的特點)

其他:

  • 降低複雜度:例如模型裁剪和剪枝,減少模型層數和參數規模
  • 改模型結構:例如模型蒸餾,通過知識蒸餾方法來獲取小模型

推理加速

半精度與權重量化

在推理中使用低精度(FP16 甚至 INT8 、二值網路、三值網路)表示取代原有精度(FP32)表示:

  • TensorRT是 NVIDIA 提出的神經網路推理(Inference)引擎,支持訓練後 8BIT 量化,它使用基於交叉熵的模型量化演算法,通過最小化兩個分佈的差異程度來實現
  • Pytorch1.3 開始已經支持量化功能,基於 QNNPACK 實現,支持訓練後量化,動態量化和量化感知訓練等技術
  • 另外 Distiller 是 Intel 基於 Pytorch 開源的模型優化工具,自然也支持 Pytorch 中的量化技術
  • 微軟的 NNI 集成了多種量化感知的訓練演算法,並支持 PyTorch/TensorFlow/MXNet/Caffe2 等多個開源框架

【參考】:

  • 有三AI:【雜談】當前模型量化有哪些可用的開源工具?https://mp.weixin.qq.com/s?__biz=MzA3NDIyMjM1NA==mid=2649037243idx=1sn=db2dc420c4d086fc99c7d8aada767484chksm=8712a7c6b0652ed020872a97ea426aca1b06adf7571af3da6dac8ce991fd61001245e9bf6e9bmpshare=1scene=1srcid=sharer_sharetime=1576667804820sharer_shareid=1d0dbdb37c6b95413d1d4fe7d61ed8f1exportkey=A6g%2Fj50pMJYVXsedNyDVh9k%3Dpass_ticket=winxjBrzw0kHErbSri5yXS88yBx1a%2BAL9KKTG6Zt1MMS%2FeI2hpx%2BmeaLsrahnlOS#rd

網路 inference 階段 Conv 層和 BN 層融合

【參考】

  • https://zhuanlan.zhihu.com/p/110552861
  • PyTorch本身提供了類似的功能,但是我沒有使用過,希望有朋友可以提供一些使用體會:https://pytorch.org/docs/1.3.0/quantization.html#torch.quantization.fuse_modules
  • 網路inference階段conv層和BN層的融合 - autocyz的文章 - 知乎 https://zhuanlan.zhihu.com/p/48005099

時間分析

  • Python 的 cProfile 可以用來分析。(Python 自帶了幾個性能分析的模塊: profilecProfilehotshot,使用方法基本都差不多,無非模塊是純 Python 還是用 C 寫的)

項目推薦

  • 基於 Pytorch 實現模型壓縮(https://github.com/666DZY666/model-compression):
  • 量化:8/4/2 bits(dorefa)、三值/二值(twn/bnn/xnor-net)
  • 剪枝:正常、規整、針對分組卷積結構的通道剪枝
  • 分組卷積結構
  • 針對特徵二值量化的BN融合

擴展閱讀

  • pytorch dataloader數據載入佔用了大部分時間,各位大佬都是怎麼解決的? - 知乎 https://www.zhihu.com/question/307282137
  • 使用pytorch時,訓練集數據太多達到上千萬張,Dataloader載入很慢怎麼辦? - 知乎 https://www.zhihu.com/question/356829360
  • PyTorch 有哪些坑/bug? - 知乎 https://www.zhihu.com/question/67209417
  • https://sagivtech.com/2017/09/19/optimizing-pytorch-training-code/
  • 26秒單GPU訓練CIFAR10,Jeff Dean也點贊的深度學習優化技巧 - 機器之心的文章 - 知乎 https://zhuanlan.zhihu.com/p/79020733
  • 線上模型加入幾個新特徵訓練後上線,tensorflow serving預測時間為什麼比原來慢20多倍? - TzeSing的回答 - 知乎 https://www.zhihu.com/question/354086469/answer/894235805
  • 相關資料 · 語雀 https://www.yuque.com/lart/gw5mta/bl3p3y
  • ShuffleNetV2:https://arxiv.org/pdf/1807.11164.pdf
  • 今天,你的模型加速了嗎?這裡有5個方法供你參考(附代碼解析): https://mp.weixin.qq.com/s?__biz=MzI0ODcxODk5OA==mid=2247511633idx=2sn=a5ab187c03dfeab4e64c85fc562d7c0dchksm=e99e9da8dee914be3d713c41d5dedb7fcdc9982c8b027b5e9b84e31789913c5b2dd880210eadmpshare=1scene=1srcid=sharer_sharetime=1576934236399sharer_shareid=1d0dbdb37c6b95413d1d4fe7d61ed8f1exportkey=A%2B3SqYGse83qyFva%2BYSy3Ng%3Dpass_ticket=winxjBrzw0kHErbSri5yXS88yBx1a%2BAL9KKTG6Zt1MMS%2FeI2hpx%2BmeaLsrahnlOS#rd
  • pytorch常見的坑匯總 - 鬱振波的文章 - 知乎 https://zhuanlan.zhihu.com/p/77952356
  • Pytorch 提速指南 - 雲夢的文章 - 知乎 https://zhuanlan.zhihu.com/p/39752167


1)小圖拼起來存放(降低讀取次數)

2)存bmp圖(降低解碼時間)

3)1張32*32的圖其實也就3K大,1000w也纔不到29G,現在訓練機器都是幾百G的內存,直接載到內存裡面,或者把把內存映射成磁碟好了。


io對cpu壓力不大的。90%的cpu肯定是在做計算。

讀寫的上限跟iops有關,iops又跟硬碟有關,拿阿里雲的普通ssd說的話,代碼寫的還行的話,一秒最多讀300-400m。載入慢可以先試試自己讀出來在做轉換。

訓練慢的話就上gpu吧。數據該壓縮的地方壓縮一下。


首先判斷是否是io瓶頸,數據數量多少和io速度沒關係,cpu很高的話說明問題在於cpu預處理而非磁碟io。

既然已經都幾千萬樣本了,個人認為就沒必要做實事的數據增強和預處理了。

離線數據增強好,load進去後直接餵給gpu就可以了。


1. DALI

2. 掛載內存檔tmpfs


推薦閱讀:
相關文章