东亚银行、岚图汽车带你解锁 AIGC 时代的数字化人才培养各赛道新模式! 了解详情
写点什么

Spark on Angel:Spark 机器学习的核心加速器

  • 2017-08-20
  • 本文字数:4423 字

    阅读完需:约 15 分钟

Spark 的核心概念是 RDD,而 RDD 的关键特性之一是其不可变性,来规避分布式环境下复杂的各种并行问题。这个抽象,在数据分析的领域是没有问题的,它能最大化的解决分布式问题,简化各种算子的复杂度,并提供高性能的分布式数据处理运算能力。

然而在机器学习领域,RDD 的弱点很快也暴露了。机器学习的核心是迭代和参数更新。RDD 凭借着逻辑上不落地的内存计算特性,可以很好的解决迭代的问题,然而 RDD 的不可变性,却非常不适合参数反复多次更新的需求。这本质上的不匹配性,导致了 Spark 的 MLlib 库,发展一直非常缓慢,从 2015 年开始就没有实质性的创新,性能也不好。

为此,Angel 在设计生态圈的时候,优先考虑了 Spark。在 V1.0.0 推出的时候,就已经具备了 Spark on Angel 的功能,基于 Angel 为 Spark 加上了 PS 功能,在不变中加入了变化的因素,可谓如虎添翼。

我们将以 L-BFGS 为例,来分析 Spark 在机器学习算法的实现上的问题,以及 Spark on Angel 是如何解决 Spark 在机器学习任务中的遇到的瓶颈,让 Spark 的机器学习更加强大。

1. L-BFGS 算法说明

L-BFGS 模型参数更新过程如下:

计算 pk = Hk-1 gk 伪代码如下所示,这是人们常说的 two-loop recursion 算法,是 Limited-BFGS 算法的核心部分。
返回值 r 是我们说要的 pk。

其中,H0-1 是单位阵,yk=gk-gk-1, sk=wk-w k-1k-1,L-BFGS 算法将最近 m 轮生成的 yk 和 sk 序列,记做 {yk} 和 {sk}。基于计算 {yk} 和 {sk} 计算 pk 。

2.L-BFGS 的 Spark 实现

2.1 实现框架

Spark 中的 driver 负责协调整个 Spark 任务执行的同时,需要保存最近 m 轮的 {yk} 和 {sk} 序列,并在 driver 上执行 two-loop recursion 算法。而 executor 负责分布式地计算梯度向量。

迭代过程:
(1)每轮迭代,将每个 executor 计算的梯度 Aggregate 到 driver
(2)yk 和 sk 保存在 driver 上,在 driver 端执行 two-loop recursion 算法
(3)driver 上更新模型 w,并将 w 广播到每个 Executor

2.2 性能分析

基于 Spark 的 L-BFGS 实现的算法优点比较明显:

  • HDFS I/O
    Spark 可以快速读写 HDFS 上的训练数据;
  • 细粒度的负载均衡
    并行计算梯度时,Spark 具有强大的并行调度机制,保证 task 快速执行;
  • 容错机制
    当计算节点挂掉、任务失败,Spark 会根据 RDD 的 DAG 关系链实现数据的重计算。但是对于迭代式算法,每轮迭代要用 RDD 的 action 操作,打断 RDD 的 DAG,避免因为重计算引起逻辑的错乱;
  • 基于内存的计算
    基于内存的计算过程,可以加速机器学习算法中计算梯度过程的耗时。

该实现的缺点:

  • treeAggregate 引起的网络瓶颈
    Spark 用 treeAggregate 聚合梯度时,如果模型维度达到亿级,每个梯度向量都可能达到几百兆;此时 treeAggregate 的 shuffle 的效率非常低;

  • driver 单点

    • 保存{yk}和{sk}序列需要较大的内存空间;
    • two-loop recursion 算法是由 driver 单点执行,该过程是多个高维度的向量的运算;
    • 每轮迭代,driver 都需要和 executor 完成高维度向量的 aggregate 和 broadcast。

3.L-BFGS 的 Spark on Angel 实现

3.1 实现框架

Spark on Angel 借助 Angel PS-Service 的功能为 Spark 引入 PS 的角色,减轻整个算法流程对 driver 的依赖。two-loop recursion 算法的运算交给 PS,而 driver 只负责任务的调度,大大减轻的对 driver 性能的依赖。

Angel PS 由一组分布式节点组成,每个 vector、matrix 被切分成多个 partition 保存到不同的节点上,同时支持 vector 和 matrix 之间的运算;

{yk} 和 {sk} 序列分布式地保存到 Angel PS 上,two-loop recursion 算法中高维度的向量计算也是在 PS 上完成。Spark executor 每轮迭代过程会从 PS 上Pull w 到本地,并将计算的梯度向量Push到 PS。

迭代过程:

(1)每轮迭代,executor 将 PS 上的模型 w pull 到本地,计算梯度,然后梯度向量 push 给 PS

(2)yk 和 sk 保存在 PS 上,在 PS 端执行 two-loop recursion 算法

(3)PS 上更新模型 w

3.2 性能分析

整个算法过程,driver 只负责任务调度,而复杂的 two-loop recursion 运算在 PS 上运行,梯度的 Aggregate 和模型的同步是 executor 和 PS 之间进行,所有运算都变成分布式。在网络传输中,高维度的 PSVector 会被切成小的数据块再发送到目标节点,这种节点之间多对多的传输大大提高了梯度聚合和模型同步的速度。

这样 Spark on Angel 完全避开了 Spark 中 driver 单点的瓶颈,以及网络传输高维度向量的问题。

4.“轻易强快”的 Spark on Angel

Spark on Angel 是 Angel 为解决 Spark 在机器学习模型训练中的缺陷而设计的“插件”,没有对 Spark 做"侵入式"的修改,是一个独立的框架。可以用 “”、“”、“”、“” 来概括 Spark on Angel 的特点。

4.1 轻——"插件式"的框架

Spark on Angel 是 Angel 为解决 Spark 在机器学习模型训练中的缺陷而设计的“插件”。Spark on Angel 没有对 Spark 中的 RDD 做侵入式的修改,Spark on Angel 是依赖于 Spark 和 Angel 的框架,同时其逻辑又独立于 Spark 和 Angel。

因此,Spark 用户使用 Spark on Angel 非常简单,只需在 Spark 的提交脚本里做三处改动即可,详情可见 Angel 的 Github Spark on Angel Quick Start 文档

可以看到提交的 Spark on Angel 任务,其本质上依然是一个 Spark 任务,整个任务的执行过程与 Spark 一样的。

复制代码
source ${Angel_HOME}/bin/spark-on-angel-env.sh
$SPARK_HOME/bin/spark-submit \
--master yarn-cluster \
--conf spark.ps.jars=$SONA_ANGEL_JARS \
--conf spark.ps.instances=20 \
--conf spark.ps.cores=4 \
--conf spark.ps.memory=10g \
--jars $SONA_SPARK_JARS \
....

Spark on Angel 能够成为如此轻量级的框架,得益于 Angel 对 PS-Service 的封装,使 Spark 的 driver 和 executor 可以通过 PsAgent、PSClient 与 Angel PS 做数据交互。

4.2 强——功能强大,支持 breeze 库

breeze 库是 scala 实现的面向机器学习的数值运算库。Spark MLlib 的大部分数值优化算法都是通过调用 breeze 来完成的。如下所示,Spark 和 Spark on Angel 两种实现都是通过调用breeze.optimize.LBFGS实现的。Spark 的实现是传入的类型是 breeze 库的DenseVector,而 Spark on Angel 的实现是传入BreezePSVector

BreezePSVector是指 Angel PS 上的 Vector,该 Vector 实现了 breeze NumericOps 下的方法,如常用的 dot,scale,axpy,add 等运算,因此在LBFGS[BreezePSVector] two-loop recursion 算法中的高维度向量运算是BreezePSVector之间的运算,而BreezePSVector之间全部在 Angel PS 上分布式完成。

  • Spark 的 L-BFGS 实现
复制代码
import breeze.optimize.LBFGS
  val lbfgs = new LBFGS[DenseVector](maxIter, m, tol)
  val states = lbfgs.iterations(Cost(trainData), initWeight)
<div class="md-section-divider"></div>
  • Spark on Angel 的 L-BFGS 实现
    接口调用里的 Vector 泛型从DenseVector变成 BreezePSVector
复制代码
  import breeze.optimize.LBFGS
  val lbfgs = new LBFGS[BreezePSVector](maxIter, m, tol)
  val states = lbfgs.iterations(PSCost(trainData), initWeightPS)
<div class="md-section-divider"></div>

4.3 易——编程接口简单

Spark 能够在大数据领域这么流行的另外一个原因是:其编程方式简单、容易理解,Spark on Angel 同样继承了这个特性。

Spark on Angel 本质是一个 Spark 任务,整个代码实现逻辑跟 Spark 是一致的;当需要与 PSVector 做运算时,调用相应的接口即可。

如下代码所示,LBFGS 在 Spark 和 Spark on Angel 上的实现,二者代码的整体思路是一样的,主要的区别是梯度向量的 Aggregate 和模型 的 pull/push。
因此,如果将 Spark 的算法改造成 Spark on Angel 的任务,只需要修改少量的代码即可。

L-BFGS 需要用户实现DiffFunctionDiffFunctioncalculte接口输入参数是 ,遍历训练数据并返回 loss 和 gradient。

其完整代码,请前往 Github SparseLogistic

  • Spark 的DiffFunction实现
复制代码
  case class Cost(trainData: RDD[Instance]) extends DiffFunction[DenseVector] {
    def calculate(w: DenseVector): (Double, DenseVector) = {
      // 广播 w
      val bcW = sc.broadcast(w)
      // 通过 treeAggregate 的方式计算 loss 和 gradient
      val (cumGradient, cumLoss) = trainData
        .treeAggregate((new DenseVector(x.length), 0.0)) (seqOp, combOp)
      val resGradient = new DenseVector(cumGradient.toArray.map(_ / sampleNum))
      (cumLoss / sampleNum, resGradient)
    }
<div class="md-section-divider"></div>
  • Spark on Angel 的 DiffFunction 实现

calculate接口输入参数是 w ,遍历训练数据并返回 loss 和 cumGradient。其中 w 和 cumGradient都是BreezePSVector;计算梯度时,需要将 Pull 到本地,本地的 gradient 值,需要通过PSVectorincrementAndFlush方式 Push 到远程 PS 上的cumGradient向量。

复制代码
case class PSCost(trainData: RDD[Instance]) extends DiffFunction[BreezePSVector] {
override def calculate(w: BreezePSVector): (Double, BreezePSVector) = {
// 初始化 gradient 向量:cumGradient
val cumGradient = pool.createZero().mkBreeze()
// 计算梯度和 loss
val cumLoss = trainData.mapPartitions { iter =>
// pull 模型 w 到 executor 本地
val localW = w.toRemote.pull()
val (gradient, loss) = calculateGradAndLoss(iter, localW)
// incement 本地的 grad 到 PS 的 cumGradient
cumGradient.toRemote.incrementAndFlush(gradient)
Iterator.single(loss)
}.sum()
cumGradient *= 1.0 / sampleNum
(cumLoss / sampleNum, cumGradient)
}
}

4.4 快——性能强劲

我们分别实现了 SGD、LBFGS、OWLQN 三种优化方法的 LR,并在 Spark 和 Spark on Angel 上做了实验对比。
该实验代码请前往 Github SparseLRWithX.scala

  • 数据集:腾讯内部某业务的一份数据集,2.3 亿样本,5 千万维度
  • 实验设置:
    说明 1:三组对比实验的资源配置如下,我们尽可能保证所有任务在资源充足的情况下执行,因此配置的资源比实际需要的偏多;
    说明 2:执行 Spark 任务时,需要加大 spark.driver.maxResultSize 参数;而 Spark on Angel 就不用配置此参数。

如上数据所示,Spark on Angel 相较于 Spark 在训练 LR 模型时有 50% 以上的加速;对于越复杂的模型,其加速的比例越大。

5. 结语

Spark on Angel 的出现可以高效、低成本地克服 Spark 在机器学习领域遇到的瓶颈;我们将继续优化 Spark on Angel,并提高其性能。也欢迎大家在 Github 上一起参与我们的改进。

Angel 项目 Github: Angel ,喜欢的话到 Github 上给我们 Star。


感谢蔡芳芳对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

公众号推荐:

2024 年 1 月,InfoQ 研究中心重磅发布《大语言模型综合能力测评报告 2024》,揭示了 10 个大模型在语义理解、文学创作、知识问答等领域的卓越表现。ChatGPT-4、文心一言等领先模型在编程、逻辑推理等方面展现出惊人的进步,预示着大模型将在 2024 年迎来更广泛的应用和创新。关注公众号「AI 前线」,回复「大模型报告」免费获取电子版研究报告。

AI 前线公众号
2017-08-20 19:001993

评论

发布
暂无评论
发现更多内容

Dio 封装之金屋藏娇

岛上码农

flutter ios开发 安卓开发 4月月更 跨平台开发

元宇宙(Metaverse)对普通人意味着什么?

涛哥 数字产品和业务架构

元宇宙

苹果手机怎么恢复备份?iOS备份恢复教程

茶色酒

苹果手机备份

元宇宙是人类的终极未来吗?

涛哥 数字产品和业务架构

元宇宙

imazingAPP软件怎么安装到苹果手机电脑上面?

茶色酒

imazing

丙午篇 「準佛」 《「內元宇宙」聯載》

因田木

陰陽五行

C语言总结_数组全方位练习

DS小龙哥

4月月更

业务架构师的思维转变

涛哥 数字产品和业务架构

[Day24]-[二叉树] 相同树

方勇(gopher)

LeetCode 二叉树 DFS BFS 数据结构算法

Docker下,极速体验pinpoint1.6.3

程序员欣宸

Java 分布式 4月月更

ThinkPHP6+swoole+easywechat使用教程

CRMEB

Plato Farm的“P2E”经济模型,赚取更多的MARK是关键

BlockChain先知

企业架构的7个关键趋势

涛哥 数字产品和业务架构

企业架构

云原生训练营 -Week10

jjn0703

云原生训练营

Go 语言入门很简单:正则表达式

宇宙之一粟

正则表达式 Go 语言 4月月更

别再用老版云效Projex项目协作了,该升级了

阿里云云效

阿里云 项目管理 研发团队 项目协作 项目协作工具

大数据培训Spark SQL底层执行流程

@零度

Sparksql 大数据开发

提前起跑的OPPO,靠闪充完成一次“三级跳”

脑极体

微服务与领域驱动设计,架构实践总结

架构 微服务 领域驱动设计 软件架构

想学习算法交易的工程师们,机会来啦~

非凸科技

rust 招聘 基金 量化交易 算法交易

《Mybatis 手撸专栏》第6章:数据源池化技术实现

小傅哥

Java 面试 小傅哥 mybatis 源码学习

Spark SQL 字段血缘在 vivo 互联网的实践

vivo互联网技术

大数据 spark Sparksql 数据处理

微信小程序开发系列 (三) :微信小程序如何响应用户点击事件和微信平台 API 的使用方法介绍

Jerry Wang

微信小程序 微信公众平台 前端开发 4月月更 微信平台

imazing是什么软件?

茶色酒

imazing

什么是瀑布开发?适用于哪些场景?有哪些瀑布开发管理系统?

PingCode

华为云大咖带你玩转云原生基础设施之K8s

坚果

4月月更

自己动手写 Docker 系列 -- 6.5 启动时给容器配置网络

Go Docker 4月月更

我们需要一个元宇宙吗?

涛哥 数字产品和业务架构

元宇宙

元宇宙或许翻译错了

涛哥 数字产品和业务架构

元宇宙

redis优化系列(四)哨兵机制

乌龟哥哥

4月月更

云原生训练营学习总结

arctec

Spark on Angel:Spark机器学习的核心加速器_语言 & 开发_云加社区_InfoQ精选文章