【技術分享】caffe2分布式平臺安裝部署文檔
本文旨在搭建部署Caffe2的分布式環境,支持多機多GPU的神經網絡訓練,最后以resnet50為例進行分布式訓練。
1??????環境準備
1.1??????系統準備
1.1.1????????物理服務器環境
三臺服務器,硬件配置如下:
服務器名稱
CPU
內存
GPU
顯存
server1
Xeon E5-2680 v4
440 GB
Tesla P100
16 GB
server2
Xeon E5-2680 v4
440 GB
Tesla P100
16 GB
server3
Xeon E5-2680 v4
440 GB
Tesla P4
8 GB
系統環境如下:
服務器名稱
系統
IP
CUDA版本
server1
Ubuntu 16.04
192.168.133.10
8.0
server2
Ubuntu 16.04
192.168.133.11
8.0
server3
Ubuntu 16.04
192.168.133.12
8.0
在每個服務器上安裝docker,隨后安裝nvidia-docker插件這里不再給出步驟,參考https://docs.docker.com/install/linux/docker-ce/ubuntu/
https://github.com/NVIDIA/nvidia-docker/wiki/Frequently-Asked-Questions#setting-up
1.1.2????????容器環境準備
選擇某個物理主機,創建一個鏡像,并且編譯caffe2,隨后將鏡像保存后push到私有倉庫,其他物理主機直接拉取鏡像即可完成包含caffe2的容器創建,這里選擇server1。
在server1物理服務器上拉取NVIDIA包含cuda的官方鏡像,地址https://hub.docker.com/r/nvidia/cuda/(這里沒有直接拉取caffe2的官方鏡像,是為了能夠方便自行編譯,并且caffe2官方鏡像中的版本時間較早,不一定能滿足需求)這里選擇了包含CUDA 8.0的devel版本,方便編譯caffe2(base和runtime版本不支持cuda應用的源碼編譯,只支持編譯好的應用)。
docker pull nvidia/cuda:8.0-devel-ubuntu16.04
使用nvidia-docker啟動容器,支持GPU。
nvidia-docker run -it --name caffe2 --net=host --hostname caffe2 --dns 8.8.8.8 –v /mnt:/mnt nvidia/cuda:8.0-devel-ubuntu16.04 bash
容器操作系統:Ubuntu 16.04,64位版本,用戶:root
1.2??????網絡配置
容器內的操作系統需要proxy代理方能連接yum源安裝軟件包。
本文使用的代理是http://192.168.5.18:3128,編輯根目錄下的.bashrc?或者/etc/profile文件,在最后增加如下幾行:
export http_proxy="http://192.168.5.18:3128"
export https_proxy="http://192.168.5.18:3128"
export ip_range=$(echo 192.168.79.{1..255} | sed 's/ /,/g')
export no_proxy="localhost,127.0.0.1,$ip_range,.huawei.com"
之后source .bashrc?或者?source /etc/profile即可。
使用curl baidu.com驗證,如果有內容輸出說明網絡已連通。
2??????部署caffe2
首先在單個節點的容器中完成caffe2的編譯安裝,隨后拓展到其他節點。
2.1??????安裝依賴包
2.1.1????????配置軟件源
由于鏡像中沒有編輯器,先安裝vim
apt-get update && apt-get install vim
更換軟件源(速度更快一點),首先備份已有源
cd /etc/apt && mv sources.list sources.list.bk
下載或者通過vim將163或者阿里源寫入sources.list中。
deb http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.163.com/ubuntu/ trusty-backports main restricted universe multiverse
更新列表
apt-get update
2.1.2????????安裝依賴包
apt-get install openssh-server
apt-get install -y --no-install-recommends build-essential cmake git libgoogle-glog-dev libgtest-dev libiomp-dev libleveldb-dev liblmdb-dev libopencv-dev libopenmpi-dev libsnappy-dev libprotobuf-dev openmpi-bin openmpi-doc protobuf-compiler protobuf-c-compiler libgflags-dev python-dev python-pip python-setuptools graphviz
與官方推薦的依賴包相比增加了一些必要的依賴包。
2.1.3????????安裝python依賴庫
sudo pip install flask future hypothesis numpy protobuf pydot python-nvd3 pyyaml requests scikit-image scipy setuptools six tornado jupyter matplotlib pydot
與官方推薦的庫相比增加了一些必要的庫。
2.1.4????????安裝cuDNN
由于鏡像中包含了CUDA,所以這里只需要安裝cuDNN加速庫即可,兩種方法:
安裝cuDNN方法1:
添加源
echo "deb http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64 /" > /etc/apt/sources.list.d/nvidia-ml.list
更新列表并安裝
apt-get update
apt-get install -y --no-install-recommends libcudnn7=7.1.2.21-1+cuda8.0 libcudnn7-dev=7.1.2.21-1+cuda8.0
rm -rf /var/lib/apt/lists/*
安裝cuDNN方法2:
下載源碼包并解壓,在https://developer.nvidia.com/rdp/cudnn-download下載cuDNN支持8.0的版本
tar -xzvf cudnn-8.0-linux-x64-v7.1.tgz
cd cuda/include/cudnn.h /usr/local/cuda/include/
cp cuda/lib64/libcudnn* /usr/local/cuda/lib64/
rm cudnn-8.0-linux-x64-v7.1.tgz && sudo ldconfig
配置環境變量
export PATH=/usr/local/cuda-8.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:/usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH
2.2??????編譯Caffe2
2.2.1????????下載caffe2源代碼
下載方法1:
cd /opt && git clone --recursive https://github.com/caffe2/caffe2.git
下載方法2:
如果公司內部服務器無法直接下載,可以在windows上安裝git進行下載。注意要設置proxy?,參考http://3ms.huawei.com/km/blogs/details/5098499。(另外直接在瀏覽器下載源代碼zip的方式最終在編譯時會出錯,原因在于此類方式會少下載third-party那部分源代碼,因此必須使用git加--recursive的方式來下載這些submodule,否則它們不會直接下載)
2.2.2????????編譯安裝caffe2
cd /opt/caffe2 && mkdir build && cd build
cmake ..
make install
編譯時可能遇到cmake版本過低的問題,解決方法參考Troubleshooting。
環境變量設置
在/etc/profile中添加
export PYTHONPATH=/usr/local:$PYTHONPATH
export PYTHONPATH=/opt/caffe2/build:$PYTHONPATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
2.2.3????????測試caffe2
cd ~ && python -c 'from caffe2.python import core' 2>/dev/null && echo "Success" || echo "Failure"
輸出Success則表示成功
檢測GPU是否生效(GPU支持并且cuda安裝正常時可使用)。
python caffe2/python/operator_test/relu_op_test.py
python2 -c 'from caffe2.python import workspace; print(workspace.NumCudaDevices())'
輸出結果大于0說明GPU正常被使用,否則會報錯。
2.3??????NFS共享目錄部署
由于Caffe2在進行分布式訓練時,需要共享目錄完成參數的rendezvous,可以使用NFS或者Redis,這里選擇NFS快速搭建一個可用的分布式環境。由于容器不能直接掛載NFS共享目錄,或者這里通過物理主機映射的方式來實現共享。
2.3.1????????NFS共享服務器搭建
首先選擇一個物理主機搭建NFS server,這里選擇192.168.133.10,將/export共享出去
apt-get install nfs-kernel-server
mkdir /export
chmod 777 /export
方便重啟后NFS共享仍然生效,將其寫入/etc/exports
/export 127.0.0.1(ro,fsid=0,insecure,no_subtree_check,async)
掛載目錄
exportfs –a
2.3.2????????掛載NFS客戶端
在三個物理主機中都安裝nfs-kernel
apt-get install nfs-kernel-server
然后掛載共享目錄
mount –t nfs?192.168.133.10:/export /mnt
對于容器訪問NFS共享目錄,則在容器啟動的時候將/mnt映射上去即可。
將容器打上tag,push到私有倉庫之中,方便在其它主機上啟動。
docker push 192.168.133.11:5000/caffe2:latest
這樣該鏡像就有編譯好的caffe2和nfs-kernel
將剛才的容器關閉,以新的鏡像重新啟動一個容器
nvidia-docker run -it --name caffe2-dis --net=host --hostname caffe2 --dns 8.8.8.8 -v /mnt:/mnt? 192.168.133.11:5000/caffe2:latest? bash
在其他兩個節點上則通過拉取來獲取剛才創建的鏡像
docker pull 192.168.133.11:5000/caffe2:latest
nvidia-docker run -it --name caffe2-dis --net=host --hostname caffe2 --dns 8.8.8.8 -v /mnt:/mnt? 192.168.133.11:5000/caffe2:latest? bash
至此包含caffe2并且能訪問NFS共享目錄的分布式環境搭建完畢
2.4??????Troubleshooting
(1)編譯時遇到cmake版本過低的問題。
解決方法:通過源碼重新安裝最新版本的cmake
在http://www.cmake.org/download/中下載最新源碼包,如cmake-3.10.3.tar,然后執行解壓安裝
tar –xzvf cmake-3.10.3.tar.gz
cd cmake-3.10.3
./boostrap
make
make install
(2)linux環境下,git caffe2源碼可能遇到證書錯誤。
解決方法:將github加入到信任列表
export GIT_SSL_NO_VERIFY=1
sudo update-ca-certificates
echo -n | openssl s_client -showcerts -connect github.com:443 2>/dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
(3)make install caffe2的源碼出錯
[third_party/onnx/onnx/onnx_onnx_c2.pb.cc] Error 1
解決方法:
重新下載編譯安裝最新版本的Protobuf,地址https://github.com/google/protobuf/releases/,隨后解壓編譯安裝即可。
首先刪除原有的低版本軟件包
apt-get remove protobuf
然后解壓編譯安裝3.5.1版本
tar –xzvf protobuf-all-3.5.1.tar.gz
cd protobuf-3.5.1
./autogen.sh
./configure
make
make check
make install
如果protoc不在/usr/bin/下,可以添加連接
ln -s /usr/local/bin/protoc /usr/bin/protoc
ln -s /usr/local/lib/libprotobuf.so /usr/lib64/libprotobuf.so
不然仍然無法通過編譯。
(5)ImportError: cannot import name caffe2_pb2
環境變量設置問題,參考官網正確設置PATH,PYTHONPATH,LD_LIBRARY_PATH等變量,使用env查看是否有多余冒號等情況出現。
(6)cmake時提示無法找到cudnn庫
這是因為cuDNN的庫解壓后,沒有正確地被添加到/usr/local/cuda/下的原因,可以使用find / -name cudnn.h進行搜索,看是否存在了cudnn.h的頭文件,以確實cudnn是否被正確安裝。不能使用官網中提供的直接解壓到目錄的方法,該方法會導致沒有該庫文件存在,參考文中的方法,拷貝過去即可。
(7)ImportError: No module named _tkinter, please install the python-tk package
解決方法:sudo apt-get install python-tk
(8)如果安裝了anaconda2,可能會遇到python的依賴找不到的情況,導致cmake的時候,numpy等python都找不到。
解決方法:在PYTHONPATH中添加對應的python路徑,如/root/anaconda2/lib/python2.7/site-packages。并且在此種情況下用conda去管理安裝需要的依賴包。
(9)WARNING:root:Debug message: /root/anaconda2/bin/../lib/libstdc++.so.6: version `CXXABI_1.3.8' not found?。
解決方法:
libstdc++.so.6在系統中的位置為
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
這里出錯的原因是該文件在別的位置也存在,如Anaconda中,并且Anaconda中的版本低于系統版本(可以使用strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6查看),解決辦法是將系統中的位置都拷貝過去.
mv /root/anaconda2/lib/libstdc++.so.6 /root/anaconda2/lib/libstdc++.so.6.bk
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21 /root/anaconda2/lib/
3??????ResNet50訓練實踐
ResNet50模型是caffe2官網上給出的多GPU訓練的指導的例子,該網絡被用于圖像識別任務,常作為神經網絡訓練性能的基準測試網絡。數據集為ImageNet 1K,但是該數據集過大(約300G空間),GPU太少時訓練時間過長(兩張GPU卡要耗一周),所以這里采用它的一個子集,訓練集包含了640種車和640種船,一共1280張圖片;測試集包含了48種車和48種船,一共96張圖片,數據集總體130MB。
3.1??????單機訓練測試
單機上測試ResNet50的構建和訓練,下載數據方便進行分布式地訓練。(地址:https://github.com/caffe2/caffe2/blob/master/caffe2/python/tutorials/Multi-GPU_Training.ipynb)(單機也可以參考官網進行MNIST手寫字符識別任務的學習,地址:https://github.com/caffe2/tutorials/blob/master/MNIST.ipynb)
3.1.1????????導入數據
首先,通過代碼下載并且解壓數據(也可以手動進行),代碼:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from caffe2.python import core, workspace, model_helper, net_drawer, memonger, brew
from caffe2.python import data_parallel_model as dpm
from caffe2.python.models import resnet
from caffe2.proto import caffe2_pb2
import numpy as np
import time
import os
from IPython import display
workspace.GlobalInit(['caffe2', '--caffe2_log_level=2'])
# This section checks if you have the training and testing databases
current_folder = os.path.join(os.path.expanduser('~'), 'caffe2_notebooks')
data_folder = os.path.join(current_folder, 'tutorial_data', 'resnet_trainer')
# Train/test data
train_data_db = os.path.join(data_folder, "imagenet_cars_boats_train")
train_data_db_type = "lmdb"
# actually 640 cars and 640 boats = 1280
train_data_count = 1280
test_data_db = os.path.join(data_folder, "imagenet_cars_boats_val")
test_data_db_type = "lmdb"
# actually 48 cars and 48 boats = 96
test_data_count = 96
# Get the dataset if it is missing
def DownloadDataset(url, path):
import requests, zipfile, StringIO
print("Downloading {} ... ".format(url))
r = requests.get(url, stream=True)
z = zipfile.ZipFile(StringIO.StringIO(r.content))
z.extractall(path)
print("Done downloading to {}!".format(path))
# Make the data folder if it doesn't exist
if not os.path.exists(data_folder):
os.makedirs(data_folder)
else:
print("Data folder found at {}".format(data_folder))
# See if you already have to db, and if not, download it
if not os.path.exists(train_data_db):
DownloadDataset("http://download.caffe2.ai/databases/resnet_trainer.zip", data_folder)
代碼通過官網下載imagenet數據集,隨后將其解壓到文件夾:~/caffe2_notebooks/tutorial_data/resnet_trainer
完成后我們可以看到該文件夾下包含了imagenet_cars_boats_train和imagenet_cars_boats_val兩個文件夾,分別存儲了訓練數據集和測試數據集。這里記錄了訓練數據集和測試集的位置和數據庫類型、數據大小等信息。
3.1.2????????配置訓練參數
配置網絡訓練時采用的參數,代碼如下:
# Configure how you want to train the model and with how many GPUs
# This is set to use two GPUs in a single machine, but if you have more GPUs, extend the array [0, 1, 2, n]
gpus = [0]
# Batch size of 32 sums up to roughly 5GB of memory per device
batch_per_device = 32
total_batch_size = batch_per_device * len(gpus)
# This model discriminates between two labels: car or boat
num_labels = 2
# Initial learning rate (scale with total batch size)
base_learning_rate = 0.0004 * total_batch_size
# only intends to influence the learning rate after 10 epochs
stepsize = int(10 * train_data_count / total_batch_size)
# Weight decay (L2 regularization)
weight_decay = 1e-4
這里指定了使用的GPU、batch size、總batch size(這里單GPU就等于batch size)、標簽數量(兩類船和車)、學習速率、step size、權重衰減值。
3.1.3????????構建網絡并訓練
創建網絡并清空工作區,防止上次訓練數據產生的干擾(如果你是第二次運行的話會有影響)
train_model = model_helper.ModelHelper(name="resnet_test")
workspace.ResetWorkspace()
3.1.4????????數據讀取
創建數據讀取,從之前指定的位置讀取數據作為訓練數據。
reader = train_model.CreateDB("train_reader", db=train_data_db, db_type=train_data_db_type)
3.1.5????????圖片輸入
定義原始圖片輸入的處理方法
def add_image_input_ops(model):
# utilize the ImageInput operator to prep the images
data, label = brew.image_input(model,
reader,
["data", "label"],
batch_size=batch_per_device,
# mean: to remove color values that are common
mean=128.,
# std is going to be modified randomly to influence the mean subtraction
std=128.,
# scale to rescale each image to a common size
scale=256,
# crop to the square each image to exact dimensions
crop=224,
# not running in test mode
is_test=False,
# mirroring of the images will occur randomly
mirror=1
)
# prevent back-propagation: optional performance improvement; may not be observable at small scale
data = model.net.StopGradient(data, data)
3.1.6????????定義ResNet50網絡模型創建方法
def create_resnet50_model_ops(model, loss_scale=1.0):
# Creates a residual network
[softmax, loss] = resnet.create_resnet50(
model,
"data",
num_input_channels=3,
num_labels=num_labels,
label="label",
)
prefix = model.net.Proto().name
loss = model.net.Scale(loss, prefix + "_loss", scale=loss_scale)
brew.accuracy(model, [softmax, "label"], prefix + "_accuracy")
return [loss]
這里調用了resnet的create_resnet50方法創建網絡,該方法為caffe2官方實現,可以查看源碼深入理解。
3.1.7????????定義參數更新方法
def add_parameter_update_ops(model):
brew.add_weight_decay(model, weight_decay)
iter = brew.iter(model, "iter")
lr = model.net.LearningRate(
[iter],
"lr",
base_lr=base_learning_rate,
policy="step",
stepsize=stepsize,
gamma=0.1,
)
# Momentum SGD update
for param in model.GetParams():
param_grad = model.param_to_grad[param]
param_momentum = model.param_init_net.ConstantFill(
[param], param + '_momentum', value=0.0
)
# Update param_grad and param_momentum in place
model.net.MomentumSGDUpdate(
[param_grad, param_momentum, lr, param],
[param_grad, param_momentum, param],
momentum=0.9,
# Nesterov Momentum works slightly better than standard momentum
nesterov=1,
)
3.1.8????????梯度優化
def optimize_gradient_memory(model, loss):
model.net._net = memonger.share_grad_blobs(
model.net,
loss,
set(model.param_to_grad.values()),
# Due to memonger internals, we need a namescope here. Let's make one up; we'll need it later!
namescope="imonaboat",
share_activations=False)
3.1.9????????創建網絡并且訓練
強制指定網絡訓練使用的GPU(本機的第一個),隨后調用之前定義的方法創建網絡,并開始訓練。
# We need to give the network context and force it to run on the first GPU even if there are more.
device_opt = core.DeviceOption(caffe2_pb2.CUDA, gpus[0])
# Here's where that NameScope comes into play
with core.NameScope("imonaboat"):
# Picking that one GPU
with core.DeviceScope(device_opt):
# Run our reader, and create the layers that transform the images
add_image_input_ops(train_model)
# Generate our residual network and return the losses
losses = create_resnet50_model_ops(train_model)
# Create gradients for each loss
blobs_to_gradients = train_model.AddGradientOperators(losses)
# Kick off the learning and managing of the weights
add_parameter_update_ops(train_model)
# Optimize memory usage by consolidating where we can
optimize_gradient_memory(train_model, [blobs_to_gradients[losses[0]]])
# Startup the network
workspace.RunNetOnce(train_model.param_init_net)
# Load all of the initial weights; overwrite lets you run this multiple times
workspace.CreateNet(train_model.net, overwrite=True)
num_epochs = 1
for epoch in range(num_epochs):
# Split up the images evenly: total images / batch size
num_iters = int(train_data_count / total_batch_size)
for iter in range(num_iters):
# Stopwatch start!
t1 = time.time()
# Run this iteration!
workspace.RunNet(train_model.net.Proto().name)
t2 = time.time()
dt = t2 - t1
# Stopwatch stopped! How'd we do?
print((
"Finished iteration {:>" + str(len(str(num_iters))) + "}/{}" +
" (epoch {:>" + str(len(str(num_epochs))) + "}/{})" +
" ({:.2f} images/sec)").
format(iter+1, num_iters, epoch+1, num_epochs, total_batch_size/dt))
將以上代碼合并或者在python的交互端口依次輸入上述代碼即可開始訓練。
提示:這部分代碼與官網代碼有部分方法調用上的不同,可能是caffe2接口更新,但是官方文檔到目前為止還未更新的原因。建議在代碼中,將model.xxx創建算子的方法更改為使用brew.xxx的幫手函數方法,增加第一個參數為定義的model即可。
3.2??????分布式訓練測試
3.2.1????????下載resnet50代碼
在每個節點上完成單機測試之后,即可開始分布式的測試。訓練數據即是剛才我們下載的數據,代碼為官方在github上給出的代碼,下載下來后命名為resnet50_trainer.py。
(地址:https://github.com/caffe2/caffe2/blob/master/caffe2/python/examples/resnet50_trainer.py)
3.2.2????????重要提示
容器內進行分布式訓練,需要修改/etc/hosts,將該容器的域名解析設置為自己物理主機的IP,如
192.168.133.10? caffe2
如果不修改,會發生Gloo在通信時無法發現對方主機,無法建立socket連接(因此推測Gloo是根據IP進行通信的)。
3.2.3????????分布式訓練
訓練時需要在每個節點上依次輸入命令,在這里具體的命令為(節點更多時可以通過腳本來完成):
第一個節點:
time python resnet50_trainer.py --train_data ~/caffe2_notebooks/tutorial_data/resnet_trainer/imagenet_cars_boats_train/ --test_data ~/caffe2_notebooks/tutorial_data/resnet_trainer/imagenet_cars_boats_val/ --gpus 0 --num_labels 2 --base_learning_rate 0.0384? --batch_size 32 --epoch_size 1280 --num_epochs 10 --num_shards 3 --shard_id 0 --run_id 1234 --file_store_path=/mnt/
第二個節點:
time python resnet50_trainer.py --train_data ~/caffe2_notebooks/tutorial_data/resnet_trainer/imagenet_cars_boats_train/ --test_data ~/caffe2_notebooks/tutorial_data/resnet_trainer/imagenet_cars_boats_val/ --gpus 0 --num_labels 2 --base_learning_rate 0.0384? --batch_size 32 --epoch_size 1280 --num_epochs 10 --num_shards 3 --shard_id 1--run_id 1234 --file_store_path=/mnt/
第三個節點:
time python resnet50_trainer.py --train_data ~/caffe2_notebooks/tutorial_data/resnet_trainer/imagenet_cars_boats_train/ --test_data ~/caffe2_notebooks/tutorial_data/resnet_trainer/imagenet_cars_boats_val/ --gpus 0 --num_labels 2 --base_learning_rate 0.0384? --batch_size 32 --epoch_size 1280 --num_epochs 10 --num_shards 3 --shard_id 2 --run_id 1234 --file_store_path=/mnt/
可以看到三個節點上的命令基本相同,唯一不同的是shard-ids參數,它作為了每個節點的唯一標識,其他的參數解釋參考下一節。
3.2.4????????參數解釋
參數的解釋可以參考官網,個人的理解如下:
參數
個人理解
train_data
必備,訓練數據集的位置,文件夾即可
test_data
可選,測試數據集的位置,文件夾即可
db_type
可選,數據庫類型,默認lmdb
gpus
可選,指定當前節點上使用的gpu的ID列表,從0開始,用“,”隔開
num_gpus
可選,指定當前節點上的gpu個數,可用于替代gpu數目
num_channels
可選,圖片的顏色通道數目,默認為3
image_size
輸入圖片的像素尺寸,高或寬,假設圖片是正方形,默認227,可能不能應對小尺寸
num_labels
數據中的標簽數量,默認是1000類,可以根據輸入數據集而變化,這里的命令設置為2類
batch_size
batch的大小,這里指的是該節點上所有GPU的batch size,而不是所有節點的,單個GPU默認是32,根據該節點上的GPU數量增加
epoch_size
每個epoch輸入的數量,默認未1500000,可以自定義,如caffe2官網提供的小數據集有1280張
num_epochs
epoch數量
base_learning_rate
學習速率,官方建議設置為所有節點batch_size之和*0.0004,默認值為0.1,假設所有節點的batch size之和為256的學習速率值,根據自己設定的總batch size而改變(不是該節點上的batch size)
weight_decay
權重衰減
num_shards
分布式訓練時的機器節點數量,默認為1,單節點,
shard_id
該節點的shard ID,默認為0,將第一個節點設置為0,后續節點依次設置為1,2,3……即可
run_id
運行ID標識,用于分布式運行時,所有節點相互標識,參與該次訓練的所有節點保持一致即可
redis_host
Redis服務器的端口,用作rendezvous
redis_port
Redis服務器的IP
file_store_path
共享目錄位置,用于不同節點參數同步的臨時文件夾,作為redis的替代,兩者二選一即可,這里使用之前掛載的NFS目錄。
3.3??????簡單的性能測試
使用resnet50_trainer.py,我們在配置好的物理環境中測試分布式測試的性能,結果如下(單機命令去掉num_shards等分布式所需的命令,修改batch size即可):
服務器數目
GPU/服務器
總GPU數目
單節點Batch?size
時間(s)
1
1(p100)
1
32
415.5
1
1(p100)
1
64
585
1
1(p4)
1
32
671
2
1
2(p4+p100)
32
516
2
1
2(p100*2)
32
283
3
1
3(p100*2+p4)
32
410
該測試為單次測試結果,沒有多次重復進行,數據不嚴謹,僅作為分布式訓練能力的探測,并且部分GPU加速、網絡分發未優化。
可以看到P100和P4在性能上差距還是蠻大的,在測試過程中P4卡上batch size設置為64時便出現了out of memory的錯誤提示。因為P4卡的存在,多機分布式訓練時反而降低了訓練速度,看來使用同步的隨機梯度優化還是使用同構的硬件比較好,不然會嚴重影響效率。
3.4??????Troubleshooting
分布式過程中遇到的大部分問題,如connection error、Aborted (core dumped)都是由多節點的網絡通信異常引起的,首先是保證各個節點自己能夠解析自己的主機名(如本文中的caffe2),隨后會使用解析出來的IP進行通信,然后保證節點之間能夠順利完成通信便可以解決大部分的訓練問題。
4??????參考資料
https://caffe2.ai/docs/getting-started.html?platform=ubuntu&configuration=compile
https://caffe2.ai/docs/getting-started.html?platform=centos&configuration=cloud
https://github.com/caffe2/tutorials/blob/master/MNIST.ipynb
https://github.com/caffe2/caffe2/blob/master/caffe2/python/tutorials/Multi-GPU_Training.ipynb
https://github.com/caffe2/caffe2/blob/master/caffe2/python/examples/resnet50_trainer.py
https://blog.csdn.net/zziahgf/article/details/79022490
https://hub.docker.com/r/nvidia/cuda/
人工智能
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。