参考连接:《教你如何继续压榨GPU算力》《Multi-Process Service》
实验场景:当前有很多个任务要跑(比如调参),恰巧服务器显卡的显存也很大,跑一个任务的时候GPU利用率也没有跑满,一直在70~80%左右。这种情况下,往往让人忍不住再往上塞一个任务。然而实际上,再往上塞任务就会导致两个训练速度都很慢,总的训练时间甚至超过了串行着跑两个任务的时间,这就得不偿失了。既不想浪费算力,有能发挥大显存的优势跑多个任务,这就需要用到MPS服务器了。
解决方案:其实通过nvidia-smi和gpustat显示的GPU利用率是具有迷惑性的,这个利用率只是统计了“采样时间段内,1个及其以上的核(kernel)运行的时间的占比”,具体原理可以参考《Multi-Process Service》。也就是说,在GPU利用率100%的情况下,实际上仍有继续压榨的空间。这时候就需要用到英伟达的MPS。
具体做法:
以9号机,4卡L40为例子,下面演示如何利用英伟达MPS的加速多任务训练。
首先,运行一个任务的时候,训练速度和显卡装下如下:
可以看到,在只有1个任务的时候,训练完1个epoch需要23分钟左右,同时GPU利用率只有70~80%左右。
我们在后台在再开一个训练任务,当前任务的训练速度和显卡状态如下:
可以发现,GPU利用率虽然满了,但当前任务的训练速度下降到1h9min了,整整满了3倍。
关掉以上程序,在服务器终端进行如下操作:
export CUDA_VISIBLE_DEVICES=0,1,2,3 # 选择0,1,2,3卡。也可以不全选。
sudo nvidia-smi -i 0,1,2,3 -c EXCLUSIVE_PROCESS # 让GPU0,1,2,3变为独立进程。
sudo nvidia-cuda-mps-control -d
# 开启mps服务,这个命令输入一次即可。
输入完以上命令后,再次运行两个任务,训练速度和显卡装下如下:
可以发现,训练时间从1h9min提升到了45min左右,比原来快了很多。同时,nvidia-smi查看gpu的时候可以发现在process name里多了一个M+C的类型,而且每个gpu都多了一个nvidia cuda mps server的进程,这是MPS服务开启成功的标志。
Q&A
Q:同时训2个任务,速度也慢了一倍,总时间跟两个任务先后串行着训练没区别呀。
A1:时间上虽然总量没变,但实际上实验的时候不总是能“完美串行”着实验。举个例子,我有2个调参实验,一个实验要跑7h,晚上19:00挂上了,凌晨2:00跑完了。但凌晨2:00我是在睡觉的呀,第二天说不定几点起来呢。就算是早上6:00起来跑另一组实验,但中间不还是浪费了4个h。实际上的实验时间就成了19:00~次日13:00,总共18h。相比之下,我同时挂2实验,两个实验都需要14h,那我第二天上午9:00就能同时拿到两个实验结果(也就是说我早上8点起来都赶趟)。即完成了实验,又保证了睡眠,岂不美哉。
A2:服务器是公用的,不同用户占同一张卡的情况很常见。这种情况下开MPS服务,所有人的训练速度都得到了提升,资源也得到了充分利用。