如何自己搭建一个机器学习框架?

2023-06-01 0 164

责任编辑风险提示「想飞的木头」chan镜像:https://zhuanlan.zhihu.com/p/76541337

往后一年,他们项目组在机器学习网络平台上做过许多组织工作,即使前段时间看见两篇有关机器学习演算法与工程建设各方面的的该文,真的极为有规矩,孕育了归纳呵呵那块的许多组织工作的想法,我前段时间组织工作主要就分成四块:1,机器学习架构的研制、机器学习网络平台的构筑;2,此基础NLP潜能的销售业务全力支持。第一集该文会归纳下在机器学习架构该些控制系统工作上的许多组织工作,主要就也分成两部份:1,经典之作架构的全力支持;2,暗鞘架构的组织工作;

如何自己搭建一个机器学习框架?

如上图,是暗鞘架构的两个逻辑抽象图,整体架构分成三个角色:scheduler、Server、Worker,通过计算与存储分离,合理编排任务,达到高性能的分布式机器学习架构,这里不详细描述那块的设计,后续感兴趣会有专门的该文来描述,这里仅讨论下在暗鞘架构上的几道坎。

暗鞘架构路上的几道坎

部署组织工作

项目之初,即使基于Parameter Server的暗鞘架构,不像Spark、Hadoop有现成的作业提交控制系统,项目组开发了一套简单的实验工具,用于全力支持架构的开发:具体是基于docker作为环境的配置以及隔离工具, 暗鞘deploy工具,发布多节点训练任务,镜像内打通线上大数据环境,可以任务实验环境发布后直接拉取节点来训练模型,现阶段已有较好的任务发布、资源调度控制系统,相信随着后续迭代会更加的合理以及完全。

其实这个就是两个鸡生蛋、蛋生鸡的问题,有的人认为要暗鞘架构,需要先考虑全力支持组织工作,怎样提交、怎样监控, 连部署工具、任务调度都没有,怎么做架构?这是个特别好的问题,基建无法满足的情况应该多多少少会出现在很多项目组上,怎么办?基建无法满足,开发就没办法进行下去吗?当然不是,作为工程建设师,完全可以开发两个极简版本,全力支持你的项目开发,记住这时你的目的是架构开发而非销售业务全力支持,架构开发过程中自然会找到解决方案,以前老大经常和他们提项目之初不能过度设计,我真的还要加上一条,项目之初要抓住关键需求,然后来扣,两个复杂的控制系统永远不是完美的,也不是两个项目组可以全力支持的,要联合可以联合的项目组一起成长、一起攻克。

资源瓶颈

不管何时,资源的瓶颈或许说资源的限制一定会存在,对于两个好的控制系统一定是不断磨合不同流程、不同模块之间的性能来达到的,暗鞘架构过程中,他们学习到许多经验:定制数据处理逻辑分布式机器学习架构,尤其是大规模离散场景下,单batch的样本稀疏程度极为大, 有值特征通常不到万分之一,在一轮迭代中仅仅只更新很小一部份参数,如下图

如何自己搭建一个机器学习框架?

如图中粉红圆圈

如何自己搭建一个机器学习框架?

原则上,但数据reader去解析数据文件中的数据时,理论上一次遍历即可拿到所有数据,此处考虑到计算潜能,采用生产-消费者模式,配置好合适的cache,用来保存待消费的数据序列。放入cache的数据文件分片单位,如全力支持4个part,即表明cache内数据条数为4*part内条数据,读取文件数据时,应用format_parser来解释训练数据格式,然后进入cache, cache内部份进行shuffle,切分batch,切分batch过程中会计算每两个batch的nnz、key_set,用于后面分配计算空间以及向server拉取参数,参数拉取完成够, 每两个batch喂给计算模块去计算,shuffle batch on the fly。

可能各位大佬看见这里真的不太高效,为什么是分块的载入cache,为啥不直接使用流式处理呢 ?流式处理是不是会更高效,即使这里考虑到shuffle那块的逻辑,流式上的shuffle设计会极为复杂,这里其实他们也考虑过,比如在cache上配置两个计时器,定时进行cache内数据的shuffle,理论上可以增加一定的shuffle逻辑,但其实也无法严格保证, 当然之前他们也考虑过直接在前面读取数据时,做全局的shuffle,类似于现在图像的读取逻辑,比如类似于lmdb的存储结构,其实质在于每个样本配置两个指针用于指定数据内存块,但是在推荐场景下,一般单个样本1k-1.5k大小,样本量极为大, 如果使用lmdb这套逻辑,理论上我可以通过指针序列进行全局的shuffle,快速定位到指针位置来取样本数据, 但是如此多的指针,本身的内存占用就变得很大了,不像图像,单个指针相对整个图像内存来说几乎忽略不计,他们在尝试之后,发现样本空间变得极为巨大, 拉取数据的增长远远超过他们的预期, 而在推荐场景下这个是他们没有采用的,而是采用分数据块读取,然后local shuffle的逻辑。

拒绝数据拷贝,减少内存压力起初架构开发时,尽快他们考虑到性能问题,但多多稍稍还是没注意很多内存空间的拷贝以及不及时释放的问题,那块在单worker,或者worker数量较少的情况下,影响可忽略,但是当他们要将一台机器压到极致性能时,那块他们重新梳理了下,通过更改逻辑以及使用move操作去除 parser 等函数中不必要的数据拷(此处没有严格对比),预估能提升将近1/10的性能,尤其是训练样本数据块的拷贝,占用过多内存。

磁盘IO瓶颈他们没有想到磁盘IO瓶颈来的如此快,反而一直担心网络IO, 后来查了下机器,就释然了,实验拿到的机器竟然是很老的机械磁盘(这里真的想吐槽规划这批机器的同事),磁盘速率极低,磁盘IO的等待远远超出预期,尤其是在第两个epoch从hdfs拉到本地缓存数据和读取数据块到内存时,磁盘IO被打满了。计算耗时在最严峻时,连整体耗时的五分之一都不到,磁盘IO成为了控制系统计算的瓶颈,减少了cache内存区大小也只不过减缓了该些的压力,磁盘还是在大部份时间被打的满满的。

他们尝试过,编排数据读取部份平摊到整体任务计算的过程中,减少磁盘IO压力, 发现效果并不明显。最后他们通过将销售业务部份原始样本数据:大概480G的文本数据,通过Protobuf+gzip之后,压缩到差不多100G不到,单个文件大小从492M,转换后两个文件大小为 106M,相对降低了 78%。而读取单个文件的性能从原来的平均40s缩短至8s,相对减少了80%;,在数据读取部份进行反序列化,本以为反序列化会增加部份耗时,但发现在经过第一部份的优化之后,反序列化不增加额外耗时,且由于整体样本量减少到了1/5,磁盘IO完全不成问题了,也加上第一步的优化改造,整体的IO曲线很平稳且健康。至此,磁盘IO等待符合预期,不再用磁盘IO瓶颈。

网络瓶颈,由于现在是比较简单的模型,暂时没有看见,本个季度应该会遇到,到时候再看。

特殊需求优化

考虑到部份销售业务,并没有实时化部署线上服务,需要预先离线计算结果,然后放到线上去做推荐,他们的分布式机器学习架构也做了许多离线的inference的优化,单台机器从30万/s的处理速度优化到170万/s的速度,用5台机器,200个cpu计算核70分钟完成370亿的样本的离线计算,整体内存占用仅180G。具体优化包括以下几个各方面:

1, 数据压缩,如前面提到采用protobuf+gzip后,提升明显;2, 实现local_inference函数,即使此销售业务场景模型单机完全可以载入,去掉pull参数逻辑,直接从内存中拿到对应key,local inference时,每个worker载入全部参数;3, 修改batch inference改为单条去查询,然后多线程计算结果,这里比较违反常识,理论上同事多个样本进行计算,向量化计算效率肯定更高,但是这里即使在local inference场景下,不像训练时,组成batch的matrix效率更高,local inference计算只有两个forward,计算耗时极小,整体耗时瓶颈并不在计算上,相反由于要组成两个batch的matrix增加的耗时要大于整体计算的耗时,而单个单个可以直接查询key来进行forward计算,且这里通过openmp,可以达到多线程加速的效果。

销售业务沟通

和销售业务交流沟通,永远是做底层同学最大的一道坎,彼此视角不同、技术方向不同、愿景也有差异,在暂不成熟的销售业务上,销售业务同学永远有1000种以上的方法去提升日活、留存、转化率,技术也许只是最后两个选择。服务意识,是控制系统,尤其是像ml system这类并不是足够成熟的行业上必须要具备的,其实想想TensorFlow也就释然了,如此牛的一套东西,也还必须要全世界去pr,去培养用户使用机器学习的习惯。

如何自己搭建一个机器学习框架?

推荐阅读:

《李宏毅机器学习完整笔记》发布,Datawhale开源项目LeeML-Notes

从Word2Vec到Bert,聊聊词向量的前世今生(一)

清华姚班出身,95后博士生陈立杰获理论计算机顶会最佳学生论文

如何自己搭建一个机器学习框架?

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务