MLPerf Training 參考實現
1.MLPerf 簡介
MLPerf 官網:https://mlperf.org/
2020年7月29日,MLPerf聯盟發布了MLPerf Training v0.7的結果,這是MLPerf基准測試的第三輪結果。v0.5為第一輪,v0.6是第二輪。MLPerf基准測試是衡量機器學習性能的行業標准,顯示了行業的巨大進步和日益增長的多樣性,包括多個新的處理器,加速器和軟件框架。MLPerf Training v0.7中有兩個任務組合,一個用於常規系統,一個用於高性能計算(HPC)系統。
2.MLPerf 測試任務
MLPerf訓練測試基准包括圖像分類、翻譯、推薦系統和圍棋等8個機器學習任務中,最終結果是這8項任務的訓練時間,速度越快則性能越強。具體的8項任務內容如下:
另一個用於用於高性能計算(HPC)系統的任務內容如下:
MLPerf Training v0.7的規則參考:https://github.com/mlcommons/training_policies/blob/master/training_rules.adoc。
3.MLPerf 分類
MLPerf training可以分為封閉模型分區(Closed Model Division)和開放模型分區(Open Model Division)。其中封閉模型分區要求使用相同模型和優化器,並限制batch大小或學習率等超參數的值,它旨在硬件和軟件系統的公平比較。而開放模型分區只會限制使用相同的數據解決相同的問題,其它模型或平台都不會限制,它旨在推進ML模型和優化的創新。
4.MLPerf 評價標准
MLperf按照不同的領域問題設置了不同的Benchmark,對於MLPerf Training測試,每個Benchmark的評價標准是:在特定數據集上訓練一個模型使其達到Quality Target時的Clock time。由於機器學習任務的訓練時間有很大差異,因此,MLPerf 的最終訓練結果是由指定次數的基准測試時間平均得出的,其中會去掉最低和最高的數字,一般是運行5次取平均值,Train測試時間包含了模型構建,數據預處理,訓練以及質量測試等時間。對於MLPerf Inference測試,每個Benchmark的評價標准是:在特定數據集上測量模型的推理性能,包括Latency和吞吐量。
5.MLPerf 測試結果
MLPerf Result被定義為將模型訓練到目標質量的Clock時間,這個時間包括模型構建,數據預處理,訓練以及質量測試等時間,它通常是數小時或數天。MLPerf也提供了一個參考基准,該基准是MLPerf使用一塊 Pascal P100顯卡在未進行任何優化情況下的測試結果。下表為MLPerf Training v0.5的封閉分區的參考基准和各大廠商的測試結果。
MLperf 的結果首先按照 Division 分類,然后按照 Category 分類。結果表格中的每一行都是由單個提交者使用相同軟件堆棧和硬件平台生成的一組結果。每行包含以下信息:
名稱 | 說明 |
---|---|
Submitter | 提交結果的組織 |
Hardware | 使用的 ML 硬件類型,例如加速器或高性能 CPU。 |
Chip Count and Type | 使用的ML硬件芯片的數量,以及它們是加速器還是CPU。 |
Software | 使用的 ML 框架和主要 ML 硬件庫。 |
Benchmark result | 在各個基准測試中將模型訓練到目標質量的時間。 |
Cloud Scale | Cloud Scale源自幾家主要雲提供商的定價,並提供相對系統size/cost的粗略指標。參考單個Pascal P100系統的雲規模為1,雲規模為4的系統大約需要四倍的成本。 |
Power | 可用內部部署系統的信息。由於標准化功率測量的復雜性,此版本 MLPerf 只允許自願報告任意非官方功率信息。 |
Details | 鏈接到提交的元數據。 |
另一種結果輸出是:加速比(Speedups)。加速比是當前測試結果和使用一塊Pascal P100顯卡在未進行任何優化情況下的測試結果的比值。即當前測試結果和參考基准的比值。因此,MLPerf 的Speedups結果若是10,則表示被測試系統的訓練速度是在一塊Pascal P100上訓練同一個模型速度的10倍,訓練時間是其 1/10。下表為MLPerf Training v0.5封閉分區的參考基准和各大廠商的Speedups結果。
MLPerf Training v0.7的測試結果參考:https://mlperf.org/training-results-0-7
其它有關MLPerf Training v0.7更多信息參考官網網站:https://mlperf.org/training-overview。
Object_detection 實現步驟
本文將以MLPerf Training 中的object_detection (heavy weight) 任務為例,闡述如何利用官方的參考代碼實現其中的任務。object_detection使用Mask R-CNN with ResNet50 backbone進行模型訓練.
參考鏈接為:https://github.com/mlperf/training/tree/master/object_detection。
代碼官方來源:https://github.com/mlcommons/training/tree/master/object_detection
1.將MLPerf庫拷到本地
mkdir -p mlperf
cd mlperf
git clone https://github.com/mlperf/training.git
2.安裝CUDA、nvidia-docker和docker
source training/install_cuda_docker.sh
安裝完成后,可以查看 nvidia-docker 版本和cuda版本。
3.建立鏡像
training/object_detection/ 文件下有Dockerfile,根據此文件構建鏡像。
cd training/object_detection/
nvidia-docker build . -t mlperf/object_detection
如果顯示如下錯誤,可能是因為電腦沒有gpu。
我們需要構建如下組件,以成功實現測試。
默認鏡像構建適合 CUDA=10.0,
CUDNN=7 版本。 用如下命令也可以自己定義其它類型的版本。
nvidia-docker build -t maskrcnn-benchmark --build-arg CUDA=9.2 --build-arg CUDNN=7 docker名
鏡像構建比較緩慢,Sending build content to Docker daemon 要達到40G左右。
如果在構建鏡像過程中顯示如下錯誤,
則要更改Dockerfile文件,添加:
RUN rm /var/lib/apt/lists/* -vf
RUN apt-get clean
RUN mv /var/lib/apt/lists /tmp
RUN mkdir -p /var/lib/apt/lists/partial
RUN apt-get clean
鏡像構建完成后,docker images 查看是否構建成功,鏡像名為mlperf/object_detection。
4.准備數據
退出容器,回到本機。運行 download_dataset.sh 下載數據,download_dataset.sh 包含數據下載的相關信息。數據集為COCO2014,也可以用COCO2017。
source download_dataset.sh
打開 download_dataset.sh 查看下載的數據信息,如果shell里下載較慢,可以利用下載器下載。
本例中 download_dataset.sh 如下,我們分別用下載器下載以下四個數據:coco_annotations_minival.tgz、train2014.zip、val2014.zip、annotations_trainval2014.zip,數據量較大,四個壓縮包一共在19G左右。
#!/bin/bash
# Get COCO 2014 data sets
mkdir -p pytorch/datasets/coco
pushd pytorch/datasets/coco
curl -O https://dl.fbaipublicfiles.com/detectron/coco/coco_annotations_minival.tgz
tar xzf coco_annotations_minival.tgz
curl -O http://images.cocodataset.org/zips/train2014.zip
unzip train2014.zip
curl -O http://images.cocodataset.org/zips/val2014.zip
unzip val2014.zip
curl -O http://images.cocodataset.org/annotations/annotations_trainval2014.zip
unzip annotations_trainval2014.zip
# TBD: MD5 verification
# $md5sum *.zip *.tgz
#f4bbac642086de4f52a3fdda2de5fa2c annotations_trainval2017.zip
#cced6f7f71b7629ddf16f17bbcfab6b2 train2017.zip
#442b8da7639aecaf257c1dceb8ba8c80 val2017.zip
#2d2b9d2283adb5e3b8d25eec88e65064 coco_annotations_minival.tgz
popd
如果用下載器下載在當前目錄下,更改download_dataset.sh文件如下,再運行。
#!/bin/bash
# Get COCO 2014 data sets
mkdir -p pytorch/datasets/coco
pushd pytorch/datasets/coco
tar xzf coco_annotations_minival.tgz
unzip train2014.zip
unzip val2014.zip
unzip annotations_trainval2014.zip
popd
5.啟動鏡像
/root/worktable/ 為當前工作目錄,mlperf/object_detection 為生成鏡像的名稱。
nvidia-docker run -v /root/worktable/:/workspace -t -i --rm --ipc=host mlperf/object_detection
在鏡像生成的容器中進入工作目錄。
cd mlperf/training/object_detection
install.sh里的內容,調用了pytorch/setup.py,要去下載maskrcnn-benchmark,可以先 github 里下載下來放到pytorch目錄下。
運行 install.sh
./install.sh
6.運行Benchmark
如果是單機單卡gpu,那么直接運行 run_and_time.sh。
./run_and_time.sh
其中會涉及下載ResNet50 base,即R-50.pkl,可以先下載到本地,再把本地的R-50.pkl放到鏡像里的 /root/.torch/models/ 下。R-50.pkl的鏈接為,https://dl.fbaipublicfiles.com/detectron/ImageNetPretrained/MSRA/R-50.pkl
注意:如果單機多卡,則要更改 run_and_time.sh 里的命令
查看自己電腦gpu信息
watch -d -n 1 nvidia-smi
pytorch單機多卡訓練的命令
python -m torch.distributed.launch --nproc_per_node=你的GPU數量
YOUR_TRAINING_SCRIPT.py (--arg1 --arg2 --arg3 and all other
arguments of your training script)
對於本機,修改 run_and_time.sh

python -m torch.distributed.launch --nproc_per_node=4 \
tools/train_mlperf.py \
--config-file "configs/e2e_mask_rcnn_R_50_FPN_1x.yaml" \
SOLVER.IMS_PER_BATCH 2 \
TEST.IMS_PER_BATCH 1 \
SOLVER.MAX_ITER 720000 \
SOLVER.STEPS "(480000, 640000)" \
SOLVER.BASE_LR 0.0025
再執行 run_and_time.sh 后,就可以看到gpu都跑起來了。
中途如果報錯且它並未停止,或者中途手動停止,查看gpu信息,watch -d -n 1 nvidia-smi,會發現仍有不少進程還占用這gpu資源。有時候會由於某種原因,在關閉程序后,GPU的顯存仍處於被占用的狀態。
這時釋放顯存的方法:
sudo fuser /dev/nvidia*
該命令會顯示所有占用nvidia設備的進程pid,將這些pid逐個kill掉:kill -9 pid 。發現顯存已經被釋放。
模型采用的是基於ResNet50的Mask R-CNN ,采用的損失函數和優化器如下:

7.結果分析
按理,程序在滿足一定條件后會停止迭代,輸出得到訓練模型所用時間和加速比。
8 NVIDIA V100 GPUs 的參考結果為:https://github.com/mlcommons/training/blob/master/object_detection/pytorch/MODEL_ZOO.md
8.其它
其余基准測試實現參考:https://github.com/mlcommons/training
一般步驟都可分為:拷貝MLPerf庫--->配置環境--->安裝鏡像--->下載預處理數據--->調整參數--->啟動Benchmark
V0.6 GNMT 實現步驟
1.將MLPerf庫拷到本地
本例使用的是 training_results_v0.6,而不是mlperf / training存儲庫中提供的參考實現。
git clone https://github.com/Caiyishuai/training_results_v0.6
在此存儲庫中,有每個供應商提交的目錄(Google,Intel,NVIDIA等),其中包含用於生成結果的代碼和腳本。在NVIDIA GPU上運行基准測試。
[root@2 ~]# cd training_results_v0.6/
[root@2 training_results_v0.6]# ls
Alibaba CONTRIBUTING.md Fujitsu Google Intel LICENSE NVIDIA README.md
[root@2 training_results_v0.6]# cd NVIDIA/; ls
benchmarks LICENSE.md README.md results systems
[root@2 NVIDIA]# cd benchmarks/; ls
gnmt maskrcnn minigo resnet ssd transformer
2.下載並驗證數據集
[root@2 implementations]# pwd
/data/training_results_v0.6/NVIDIA/benchmarks/gnmt/implementations
[root@2 implementations]# ls
data download_dataset.sh pytorch verify_dataset.sh wget-log
download_dataset.sh 中包含下載數據的信息,如果已經下載在本地,要注意修改此文件。
將原來的這部分
echo "Downloading Europarl v7. This may take a while..."
wget -nc -nv -O ${OUTPUT_DIR_DATA}/europarl-v7-de-en.tgz \
http://www.statmt.org/europarl/v7/de-en.tgz
echo "Downloading Common Crawl corpus. This may take a while..."
wget -nc -nv -O ${OUTPUT_DIR_DATA}/common-crawl.tgz \
http://www.statmt.org/wmt13/training-parallel-commoncrawl.tgz
echo "Downloading News Commentary v11. This may take a while..."
wget -nc -nv -O ${OUTPUT_DIR_DATA}/nc-v11.tgz \
http://data.statmt.org/wmt16/translation-task/training-parallel-nc-v11.tgz
echo "Downloading dev/test sets"
wget -nc -nv -O ${OUTPUT_DIR_DATA}/dev.tgz \
http://data.statmt.org/wmt16/translation-task/dev.tgz
wget -nc -nv -O ${OUTPUT_DIR_DATA}/test.tgz \
http://data.statmt.org/wmt16/translation-task/test.tgz
修改為:
echo "Downloading Europarl v7. This may take a while..."
mv -i data/de-en.tgz ${OUTPUT_DIR_DATA}/europarl-v7-de-en.tgz \
echo "Downloading Common Crawl corpus. This may take a while..."
mv -i data/training-parallel-commoncrawl.tgz ${OUTPUT_DIR_DATA}/common-crawl.tgz \
echo "Downloading News Commentary v11. This may take a while..."
mv -i data/training-parallel-nc-v11.tgz ${OUTPUT_DIR_DATA}/nc-v11.tgz \
echo "Downloading dev/test sets"
mv -i data/dev.tgz ${OUTPUT_DIR_DATA}/dev.tgz \
mv -i data/test.tgz ${OUTPUT_DIR_DATA}/test.tgz \
數據處理需要消耗不少時間,消耗大量cpu資源。可能會造成卡頓。數據下載處理完成后,驗證數據集。
[root@2 implementations]# du -sh data/
13G data/
[root@2 implementations]# bash verify_dataset.sh
OK: correct data/train.tok.clean.bpe.32000.en
OK: correct data/train.tok.clean.bpe.32000.de
OK: correct data/newstest_dev.tok.clean.bpe.32000.en
OK: correct data/newstest_dev.tok.clean.bpe.32000.de
OK: correct data/newstest2014.tok.bpe.32000.en
OK: correct data/newstest2014.tok.bpe.32000.de
OK: correct data/newstest2014.de
3.配置文件開始准備訓練
用於執行訓練作業的腳本和代碼位於 pytorch 目錄中。
[root@2 implementations]# cd pytorch/
[root@2 pytorch]# ll
total 124
-rw-r--r-- 1 root root 5047 Jan 22 15:45 bind_launch.py
-rwxr-xr-x 1 root root 1419 Jan 22 15:45 config_DGX1_multi.sh
-rwxr-xr-x 1 root root 718 Jan 25 10:50 config_DGX1.sh
-rwxr-xr-x 1 root root 1951 Jan 22 15:45 config_DGX2_multi_16x16x32.sh
-rwxr-xr-x 1 root root 1950 Jan 22 15:45 config_DGX2_multi.sh
-rwxr-xr-x 1 root root 718 Jan 22 15:45 config_DGX2.sh
-rw-r--r-- 1 root root 1372 Jan 22 15:45 Dockerfile
-rw-r--r-- 1 root root 1129 Jan 22 15:45 LICENSE
-rw-r--r-- 1 root root 6494 Jan 22 15:45 mlperf_log_utils.py
-rw-r--r-- 1 root root 4145 Jan 22 15:45 preprocess_data.py
-rw-r--r-- 1 root root 12665 Jan 22 15:45 README.md
-rw-r--r-- 1 root root 43 Jan 22 15:45 requirements.txt
-rwxr-xr-x 1 root root 2220 Jan 22 15:45 run_and_time.sh
-rwxr-xr-x 1 root root 7173 Jan 25 10:56 run.sub
drwxr-xr-x 3 root root 45 Jan 22 15:45 scripts
drwxr-xr-x 7 root root 90 Jan 22 15:45 seq2seq
-rw-r--r-- 1 root root 1082 Jan 22 15:45 setup.py
-rw-r--r-- 1 root root 25927 Jan 22 15:45 train.py
-rw-r--r-- 1 root root 8056 Jan 22 15:45 translate.py
需要配置config_
要編輯的參數:
DGXNGPU = 4
DGXSOCKETCORES = 10
DGXNSOCKET = 2
可以使用 nvidia-smi 命令獲取GPU信息,並使用 lscpu 命令獲取CPU信息,尤其是:
Core(s) per socket: 18
Socket(s): 2
注意:在 run_and_time.sh 文件中也寫入上述參數,為防止最終測試失敗,在建立鏡像前,就應確保參數設置正確。否則運行時會出現 numactl <n-m,n-m> 的錯誤
下圖為對 config_DGX1.sh 內的修改。

下圖為對run_and_time.sh內的修改。

4.構建鏡像
docker build -t mlperf-nvidia:rnn_translator .
鏡像構建需要花不少時間。查看一下dockfile文件。
ARG FROM_IMAGE_NAME=nvcr.io/nvidia/pytorch:19.05-py3
FROM ${FROM_IMAGE_NAME}
# Install dependencies for system configuration logger
RUN apt-get update && apt-get install -y --no-install-recommends \
infiniband-diags \
pciutils && \
rm -rf /var/lib/apt/lists/*
# Install Python dependencies
WORKDIR /workspace/rnn_translator
COPY requirements.txt .
RUN pip install --no-cache-dir https://github.com/mlperf/training/archive/6289993e1e9f0f5c4534336df83ff199bd0cdb75.zip#subdirectory=compliance \
&& pip install --no-cache-dir -r requirements.txt
# Copy & build extensions
COPY seq2seq/csrc seq2seq/csrc
COPY setup.py .
RUN pip install .
# Copy GNMT code
COPY . .
# Configure environment variables
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8
注意:Docker 報錯 Please provide a source image with from
prior to commit,是因為Dockerfile的From之前不能使用ARG,允許這種用法是在docker 17.05.0-ce (2017-05-04)之后才引入的。因此要升級docker版本,查看我的docker版本。
[root@2 pytorch]# docker version
Client: Docker Engine - Community
Version: 20.10.2
API version: 1.41
Go version: go1.13.15
Git commit: 2291f61
Built: Mon Dec 28 16:17:48 2020
OS/Arch: linux/amd64
Context: default
Experimental: true
…………
5.運行Benchmark
對於本測試,將使用config_DGX1.sh並因此將DGXSYTEM指定為DGX1。還要將PULL設置為0,以指示使用本地映像而不是從存儲庫中提取docker映像。創建了一個新目錄“ logs”來存儲基准日志文件,並在啟動基准運行時提供數據目錄路徑,如下所示:
DATADIR=/data/training_results_v0.6/NVIDIA/benchmarks/gnmt/implementations/data
LOGDIR=/data/training_results_v0.6/NVIDIA/benchmarks/gnmt/implementations/logs
PULL=0 DGXSYSTEM=DGX1
注意:以上參數應寫在 run.sub文件里,運行前必須先修改。
如下圖所示, vim run.sub ,中 run.sub 中增加上述語句。
閱讀 run.sub 會發現,之后命令中涉及啟動鏡像,啟動鏡像的命令保存在 DOCKEREXEC 中,並且會把上述 data 和 logs掛載到鏡像。
最后運行 run.sub
./run.sub
注意:運行時會出現 numactl <n-m,n-m> 的錯誤,提示 cpu ranges out of the actual range 的錯誤,可能是因為參數沒有設置正確。但是僅僅在容器中的 run_and_time.sh 或 config_DGX1.sh 是不行的,可以選擇修改完成后,將容器用 docker commit 命令保存為鏡像。
如果 RuntimeError: cuda runtime error (209) : no kernel image is available for execution on the device,可能是 pytorch和 cuda 版本不匹配,也有可能是算力不足。測試 pytorch 和 cuda的兼容性。
import torch
import torchvision
print(torch.cuda.is_available())
a = torch.Tensor(5,3)
a=a.cuda()
print(a)
一般來講,輸出主要是報48號錯誤,也就是CUDA的問題,出現這個問題在於硬件的支持情況。本例中報209錯誤,在容器中測試 pytorch和 cuda 版本匹配,原因可能是算力不足。