jasperzhong / read-papers-and-code

My paper/code reading notes in Chinese
45 stars 3 forks source link

MLSys '20 | Resource Elasticity in Distributed Deep Learning #148

Closed jasperzhong closed 3 years ago

jasperzhong commented 3 years ago

https://www.cs.princeton.edu/~andrewor/deep-learning-elasticity.pdf

jasperzhong commented 3 years ago

elasticity是指可以根据资源需求scale out or in. 这可以提高系统效率,节约成本. 但是目前仍然是fix set of resources为主,这有几个原因:

  1. 因为目前的框架比如Tensorflow在设计的时候没考虑这个问题. (后来Horovod有了elastic方案)
  2. 对于已知的workload, 比如training ResNet on ImageNet, 这都被训练烂了,需要多少卡,超参该怎么调早就知道了,比如每张卡的batch size一般用64/128,64张V100大概两个半小时训练完. 但是对于未知的workload,不存在这样的guidelines,用户必须要自己去trail-and-error来找到合适的资源. 但是trail-and-error这样做代价很高. 比如,我们不知道这个任务的scaling efficiency是多少,也就不能确定要分配多少资源.

因此,目前大家都是分配fixed set of resources,这样显然不是最优的. 首先我们不能确定需要多少资源; 其次,就算知道了,分配的资源也会存在straggler,导致整体性能下降.

这就是elastic training comes in的地方了. 但这里的挑战除了engineering effor,还有一些算法上的问题:

  1. 单独用资源利用率作为衡量指标是有局限性的,应该兼顾throughput
  2. scaling out会改变total batch size,这会影响convergence rate

对于batch size这个问题. 确实很麻烦. 增加新的worker,我们要么

  1. 保持local batch size不变,这会增加global batch size -> 影响convergence rate
  2. 保持global batch size不变,这会降低local batch size -> 降低per device throughput

最后这篇paper也只是取了一个折中的方法: 用户给定一个maximum global batch size. 如果没给定,系统默认large batch size不会显著影响这个模型的convergence.

image

这个design很像今年OSDI的 #102 ,用monitoring statistics来反馈runtime. 检测的数据有两个

  1. scaling efficiency. 这里用的定义很有意思,感觉以后可以参考

image

  1. utility vs cost. 害, 用户根本不关心scaling efficiency, 用户只关心dollar cost和job completion time. 增加worker可以降低job completion time, 但是会提高每分钟的dollar cost, 那最后到底是提高了还是降低了总的dollar cost呢? 不知道! 下面是作者的一个实测:

image

作者引入了效用的概念,这是经济学的术语,表示消费者对于商品或者服务的满意度. 显然,时间越短,效用应该越高. 但效用本身是抽象的概念,具体是什么样是用户决定的. 作者分析了三种情况:

image

所以,给定效用函数U(T),和代价函数C(k),我们就能确定最优的k是多少. 具体来说,由于T是k的函数,遍历k,找到minimize U(T(k)) - C(k)的就行了. 这样做有一个问题,就是如果U(T)是平的,也就是我们无所谓多少时间训练完成,那么这个做法会不断增加机器. 所以最后使用的是边际效用边际成本.

image

但是代价函数一开始是不知道的,因为不知道scaling efficiency. 所以得靠系统自己去发现.

straggler是通过检测runtime statistics来判断 - 长期低于中位数一定范围就判定为straggler.

所以整个流程应该如下: 一开始先分配几台机器跑,跑的同时收集throughput. 这时候只有一个data point,不足以make any decision. 第一步就是要增加/减少一定量的worker(除非已经达到了maximum global batch size),得到第二个data point,看是否满足 1) scaling efficiency 不太差 2) 满足上述的边际效用高于边际成本. 如果满足,那么认为这次scale out/in是有收益的,如果不满足,撤回操作. 如此反复. 大概每10个iteration就会做上述这个操作(似乎有点频繁). 另外同时还会检测straggler,及时剔除. 总体流程示意图如下:

image

实验:

  1. 看起始worker数量对于结果的影响.

CIFAR-10. 图c很有意思,无论起始是多少,很快都降低到了4块卡. 图b之所以那么低,就是因为autoscale后都只用了4块卡. image

ImageNet上有类似发现. 最后都会收敛到64块卡. image

  1. utility

改变instance价格对于选择worker数量的影响. 比如看第一张图, 如果价格涨到10块/h,会选择减少机器延长时间,而价格如果跌到0.01块/h,就会选择开更多机器,快速做完. image


这个工作确实做的很好... 效用函数这个我是真没想到. 实现细节提的不多,感觉直接在TF搞这个挺困难的.

jasperzhong commented 3 years ago

这个工作没有考虑到batch size变了,lr也要变.