基于Spark框架的大型分布式矩阵求逆运算实现(二)——大型下三角矩阵求逆运算
2018-02-25 11:19
316 查看
基于实际需要,需要对五百万阶的方阵进行求逆运算,但查看Spark(v. 2.2.0)的官方api并没有此方面的信息,就自己尝试着实现了一个;先说一下原理: 对于一个可逆矩阵A,必然会得到它的唯一LU分解,即分解为一个下三角矩阵L和一个上三角矩阵U使得 A=L*U; 我们需要求得的问题是A的逆矩阵A`,已知 A=LU,A*A`=E,所以 A` = U`*L`; 由线性代数知识可知,一个下三角矩阵的逆必然也是下三角矩阵; 又因为,逆的转置等于转置的逆,即,(U`)T = (UT),而UT和L一样是下三角矩阵,可以实现代码复用;所以问题便转化成了, (一)大型可逆矩阵的LU分解 (二)大型下三角矩阵的求逆第一部分由我的同学实现,之后会放出链接;这里主要讲一下大型下三角矩阵求逆的方法和实现;大型矩阵运算,因为数据量过大,无法在单台计算机上进行,故需要进行并行化处理,这里采用分块矩阵乘法的思想。首先设定一个步长 s,使得阶数为s的方阵可以在单台节点上进行求逆运算。根据分块矩阵乘法, L1*L1`=E L2*L1`+L3*L2`=0 L3*L3`=E化简可知, L1`=(L1)` L2`=-(L3)`*L2*(L1)` L3`=(L3)`如此一来。只要知道(L3)`,便可以知道整个矩阵的逆,而(L3)`同样是下三角矩阵,如此一来便可以进行迭代,当迭代到L3的步长不大于s时,便可以在单台节点上进行计算,如此一来,便可以反推回整个矩阵的逆;下面进入实际实现部分: 1.基于Spark的api,将HDFS上的矩阵加载到内存中,类型为 BlockMatrix 2.调用BlockMatrix.blocks方法得到底层RDD,过滤出行标不大于列标的分块(下三角矩阵上半部分全是0,减少运算量) 3.首先得到原矩阵右下角的分块,求逆得到(L3)`,行标-1,得到L1和L2,得到(L1)`和L2,如此一来便可以拼凑出原矩阵右下角分块为2的矩阵的逆,迭代运算便可得到最终结果; 期间遇到的难点: 1.矩阵加载,Spark提供的原生api无法加载CSV文件直接转成BlockMatrix,所以此处进行了封装:new IndexedRowMatrix(spark.sparkContext.textFile(path,Main.excutors).map(UDF.line2IndexedRow)).toCoordinateMatrix().toBlockMatrix(steps, steps)
/* *输入一行以逗号(英文 , )分割的浮点数,最开始的数字作为索引 *返回一个IndexRow */ def line2IndexedRow(line:String): IndexedRow ={ val arrayBuffer = line.split(",").map(_.toDouble).toBuffer val index = arrayBuffer.head.toLong arrayBuffer.trimStart(1) val vector = Vectors.dense(arrayBuffer.toArray) new IndexedRow(index,vector) }2.在计算 L2`=-(L3)`*L2*(L1)`时,由于直接调用矩阵分块乘法api会导致分块最终位置与算法设想不同,需要自行解决;3.在本地运行时结果与集群运行结果不一致:由于算法全程使用尾递归进行迭代,有部分全局变量需要广播到各个节点;4.性能优化,在矩阵运算过程中,由于是懒执行,部分变量会重复计算造成计算资源浪费,需要在SparkUI上查看,逐项调校;5.Spark的persist机制:在调用RDD的persist方法后,RDD并不会马上被缓存,而是要等到第一个action调用时才会执行,但实际上本算法中action的调用距离RDD首次生成相隔甚远,所以,需要在persist方法后接一个action来进行显示缓存;由于缓存项目过多可能造成大量IO操作,需要及时进行unpersist操作;优化后的RDD DAG截图如下:可以看到,大部分的RDD操作由于缓存,节省了大量计算资源;测试结果表明,在计算20阶,步长为5的矩阵运算时,优化前的计算时间为36.39秒;优化后,将时间缩减到10.809秒,优化成果显著;
相关文章推荐
- 基于Spark实现的超大矩阵运算
- java分布式,基于开源框架实现消息方式
- Dubbo框架应用之(四)--Dubbo基于Zookeeper实现分布式实例
- 采用Best effort 1pc + 回滚补偿机制实现的一个distributed transaction (分布式事务框架).基于dubbo rpc服务上实现。
- 基于JMS消息中间件的分布式系统初探究(一) - 通过JMS实现Web服务器与服务框架的通讯
- DCT变换及量化的c++实现(基于opencv矩阵运算)
- 基于spring+quartz的分布式定时任务框架实现
- 基于Python,scrapy,redis的分布式爬虫实现框架
- Spark上矩阵运算库(七)--LU矩阵分解实现和Spark 1.1的SVD剖析
- Dubbo框架应用之(四)--Dubbo基于Zookeeper实现分布式实例
- 基于Spring-DM实现分布式服务框架(DSF)(一)
- 基于Python,scrapy,redis的分布式爬虫实现框架
- 基于内积法的Hadoop的MapReducer框架实现稀疏矩阵乘法(java)
- 基于Python使用scrapy-redis框架实现分布式爬虫 注
- 基于Python+scrapy+redis的分布式爬虫实现框架
- 基于Spark的分布式深度学习框架BigDL开源了!
- Dubbo框架应用之(四)--Dubbo基于Zookeeper实现分布式实例
- Hive数据分析——Spark是一种基于rdd(弹性数据集)的内存分布式并行处理框架,比于Hadoop将大量的中间结果写入HDFS,Spark避免了中间结果的持久化
- C/C++语言实现矩阵求逆运算—高斯约化/消元法
- 【图像处理】矩阵运算代码实现2-矩阵求逆