WNJXYK
Thanks to the cruel world.
WNJXYKのBlog
Docker封装的简易分布式矩阵计算
Docker封装的简易分布式矩阵计算

这是一个使用Python3.6编写的简单的分布式矩阵计算的测试程序,支持分布式矩阵乘法与分布式矩阵求逆。整个项目使用Docker封装,容易批量配置。矩阵乘法使用分块乘法实现分布式,矩阵求逆使用分块消元算法实现分布式,仅仅实现功能,在网络传输、性能与并行度上依旧有所不足。

  • multiprocessing 实现分布式的任务分配
  • flask 实现Web控制界面
  • h5py 实现结果HDF5格式存储

好了,介绍完了,掏出Github链接Docker Hub链接,可以从GitHub 获得Python代码,从Docker Hub中直接拖出配置好的运行环境运行。

Docker镜像使用

  1. 首先从镜像仓库拉取本镜像。
docker pull wnjxyk/simple_distributed_matrix
  1. 从镜像新建了若干容器,例如如下代码:创建5个容器,分别映射端口号为8080、8081~8084。这里8080作为主控节点,8081~8084作为分布式计算节点。
docker run -d -it -p 8080:80 matrix python /root/Distributed_Matrix_Method/Distributed.py
docker run -d -it -p 8081:80 --cpus=0.01 matrix python /root/Distributed_Matrix_Method/Distributed.py
docker run -d -it -p 8082:80 --cpus=0.01 matrix python /root/Distributed_Matrix_Method/Distributed.py
docker run -d -it -p 8083:80 --cpus=0.01 matrix python /root/Distributed_Matrix_Method/Distributed.py
docker run -d -it -p 8084:80 --cpus=0.01 matrix python /root/Distributed_Matrix_Method/Distributed.py
  1. 浏览器中打开0.0.0.0:8080的控制页面,开始控制节点。然后进入0.0.0.0:8081~0.0.0.0:8084的控制页面,设置控制节点IP与端口,将计算节点连接到控制节点。主从IP查询可以使用docker network inspect bridge命令查询Docker局域网的结构情况之后分析获得。

  2. 返回控制节点控制页面,可以自动矩阵的大小与分块大小进行矩阵乘法与求逆操作,任务完成后可以下载HDF5格式文件核对是否计算正确(系统也会自动核对,显示为Correct即为正确)。
    https://blog.wnjxyk.cn/wp-content/uploads/2018/12/OneResult-1024x627.png

分布式效果

使用如上方法将容器建立之后,我们可以在计算节点的控制页面动态控制计算节点是否为控制节点的任务服务,通过控制启用计算节点的数量,我们就可以比较出分布式的好处。

另外值得一说的是,这里限制计算节点CPU性能是为了最大化所演示的分布式计算的效果。因为程序比较简单,并未对于网络传输与性能有所优化,所以中心的控制节点会成为性能的瓶颈。我们将控制节点的性能不设限制,计算节点的性能限制在1%,可以展现不考虑中心节点与网络传输限制的理想情况下,分布式计算的效果。

首先,我们进行单个计算节点计算矩阵乘法测试,从图中CPU占用率可以看到,我们只启用了叫做compassionate_poitras的计算节点,结果图片显示整个过程使用了60秒左右。
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/OneWorker-1024x102.png
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/OneResult-1-1024x627.png

然后,我们将四个计算节点全部都连接到控制节点上,进行同样级别的矩阵乘法运算。这次计算只用了19秒,可以看到性能提升是非常巨大的。
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/FourWorker-1024x105.png
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/FourResult-1024x623.png

紧接着,我们进行矩阵求逆的计算的性能比较,我们启用一个计算节点的时候,需要100秒完成工作,同样的运算量启用四个计算节点,就只需要26秒左右。
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/InvOne-1024x618.png
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/InvFour-1024x623.png

最终的结果会存储在HDF5格式的数据文件里,我们使用HDF View查看内部数据。其中Ans数据集是我们分布式计算出来的答案,Check数据集是使用Numpy计算出来的答案,可以通过图片粗略的观察的值,答案是正确的。
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/MultiCompare-1024x388.png
https://blog.wnjxyk.cn/wp-content/uploads/2018/12/InvCompare-1024x375.png

分布式实现

乘法与求逆元都使用了分块的思路,将一个大小为siz的矩阵分成大小为blk的分块Block_{i,j},那么会得到一个blc=\frac{siz}{blk}的方阵,其每个元素都是一个blk的方阵。

分块矩阵乘法

那么原来矩阵乘法Ans = A\cdot B,可以转化成BlockAns_{i,j} = \sum_{k=0}^{\frac{siz}{blc}}BlockA_{i,k}\cdot BlockB_{k,j}。可以看出分块之后的乘法之间是完全独立的,所以我们可以把这些耗时的矩阵乘法任务分发给计算节点运算,然后将结果返回加入结果的分块矩阵中就可以了。
假设计算节点有CNT个,我们可以把原本计算矩阵乘法的复杂度从O(n^3)变换为O(blk^3\times(\lceil \frac{blc^3}{CNT} \rceil)

Sequential Block-Based Gauss-Jordan Algorithm

实现代码可以参考之前的博客:Sequential Block-Based Gauss-Jordan Algorithm
矩阵求逆的方法使用的还是消元,不过使用了一种序列分块版本,对分布式运算更加友好。
这是一种将高斯消元的过程分块的算法,它的好处分块的过程中,块与块之间会存在很多不相关的乘法运算,利用这个性质,我们就可以将不相关的运算分散到运算节点上去。
假设计算节点有CNT个,我们可以原本O(n^3)的复杂度降低为O(blk^3\times blc \cdot (\lceil \frac{blc}{CNT}\rceil + \lceil \frac{blc\cdot (blc-1)}{CNT}\rceil))

其他

如果你是一个Docker新手,你可能会发现打开了Docker不会关闭,你可以使用一下指令将所有容器关闭。

docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)
docker rm $(docker ps -a | awk '{ print $1}' | tail -n +2)

如果你想查看一些关于正在运行的Docker容器的信息,你可以参考一下几条命令。

docker stats # CPU使用情况
docker ps # 运行中容器列表
docker ps -a  # 所有容器列表
docker network inspect bridge # 查看容器组成局域网的结构
赞赏
https://secure.gravatar.com/avatar/f83b57c055136369e9feba5d6671d6b5?s=256&r=g

WNJXYK

文章作者

一个蒟蒻

推荐文章

发表评论

textsms
account_circle
email

WNJXYKのBlog

Docker封装的简易分布式矩阵计算
这是一个使用Python3.6编写的简单的分布式矩阵计算的测试程序,支持分布式矩阵乘法与分布式矩阵求逆。整个项目使用Docker封装,容易批量配置。矩阵乘法使用分块乘法实现分布式,矩阵求逆…
扫描二维码继续阅读
2018-12-29
<--! http2https -->