首页/文章/ 详情

分布式有限元计算方法

2年前浏览1472

0. 什么是分布式计算

在这里我们定义分布式计算为使用众多CPU/GPU的并行计算,这些CPU/GPU的内存地址不能被其他CPU/GPU直接读写,只有通过网线在指定的通信协议(MPI)下进行间接操作。更具体的介绍可以参考我的下述文章。

hillyuan:有限元并行计算简介32 赞同 · 11 评论文章

当你需要快速得到你的大规模计算问题的答案,比如你的200万节点的震动解析需要在两天内得到答案的时候,采用单机内的并行计算往往实现不了这个目标。由于现在的设计人员往往需要在更改设计后经过一次模拟验证,根据我个人的面谈调查,模拟验证计算在一个晚上完成是往往可以接受的。但是如果模拟验证计算一天内还不能完成,不少人会觉得难以容忍的,这时设计人员的应对手段往往是采用分布式计算(还有一个可能是要求我们修改程序,让程序快起来^O^)。除此以外,另一个可能性就是你的计算问题大到最豪华的单机内存都容不下时,此时分布式计算是你唯一的选择。这样的问题可能是大气环流,地震海啸,整车碰触问题等等。

最后,如的标题所述,本文讲的是有限元的分布式计算。但是本文所述概念同样适应与如FDM,FVM等的分布式计算。

1. 有限元分布式计算

在此我们要考虑上图由5个节点,4个单元构成的有限元网格。虽然简单,但是用来介绍分布式计算的基本概念应该足够了。

为了便于表述,我们导入记号(几何形状维度,编号)来标记上述几何实体。如节点3标记为(0,3),单元1标记为(1,1)。如此,采用1CPU计算时,内存中保存的几何实体为

  • (0,0),(0,1),(0,2),(0,3),(0,4)

  • (1,0),(1,1),(1,2),(1,3)

其全体刚度阵的形状为


01234
0××


1×××

2
××

3

×××
4


××

在上表中,数字表示自由度编号,×表示非零成分。

1.1 数据分布1

现在我们把上述数据分布在两个CPU,把单元0,1放在CPU0,把单元2,3放在CPU1中。则此时的数据分布为:

CPU0

  • (0,0:0),(0,1:1),(0,2:2)

  • (1,0:0),(1,1:1)

CPU1

  • (0,0:3),(0,1:4) | (0,2:2)

  • (1,0:2),(1,1:3)

请注意,在此我们把前述几何实体的标记方法改为(几何形状维度,局部编号:全体编号)以对应分布式数据的变化。其中全体编号为网格文件中定义的几何实体的原有编号,局部编号为在每个CPU内重新排序的编号。各个CPU实际上是采用局部编号来进行计算。

分布式数据的另一个重要概念是持有(owned)数据非持有(ghost)数据的概念。注意到上面的数据分布中,节点2被CPU0和CPU1所共有,我们规定CPU0持有该节点,CPU1可以参照该节点,是其ghost节点(绝大多数软件都设定序号低的CPU持有数据)。为了区分持有数据和非持有数据,在上面的记号中,我们增加了一个区分符|,在该区分符后得数据为ghost数据。

此时个CPU中的刚度阵为(表中数据为局部自由度编号:全体自由度编号)

CPU0


0:01:12:23:3
0:0××

1:1×××
2:2
××

CPU1


0:31:42:2
0:3×××
1:4××
2:2×
×

CPU0持有全局自由度0,1,2,那么意味着它也持有全体刚度阵的0,1,2行。但是你要注意到全体刚度阵(2,3)的数据并不能在CPU0的计算得出,它是由CPU1计算得出,需要通过数据通信传输到CPU0. 相应的,在后续的求解过程中CPU1的ghost行往往并不介入计算。

从上面的描述我们可以看出分布式计算往往要经过两步才能完成

  • 各CPU中的计算

  • CPU间的通信。

在具体的程序实现中往往提供相应的函数要求CPU间的通信。比如在petsc中的

MatAssemblyBegin和MatAssemblyEnd

在Trilinos中的

resumeFill和fillComplete

在FrontISTR中的

hecmw_update

1.2 数据分布2

Interconnected network间的数据传输速度是分布式计算的罩门,因为它往往比CPU内部的数据传输速度低n个数量级。如何减少数据传输量是分布式计算编程中的重中之重。下面的例子是如何通过改变数据分布设计来减少通信数据量。

CPU0

  • (0,0:0),(0,1:1),(0,2:2) | (0,3:3)

  • (1,0:0),(1,1:1) | (1,2:2)

CPU1

  • (0,0:3),(0,1:4) | (0,2:2)

  • (1,0:2),(1,1:3)

在这里,我们把节点3和单元2增添为CPU0的ghost量,如此全体刚度阵的0,1,2行的数值可以从CPU0处直接计算得出,不需要与CPU1的数据通信。

CPU0


0:01:12:23:3
0:0××

1:1×××
2:2
×××
3:3

××

当然这种方法的不良后果是CPU0使用内存和计算量的增加。但是考虑到Interconnected network间的通信速度,这种牺牲往往是划算的。这种在CPU界面处多取一层ghost单元的做法也是很常见的有限元实装方法。

2. 通信的实现和控制方法

2.1 通信的实现方法

MPI提供了通信标准,最常用的函数

MPI_Sendrecv (sendbuf,sendcount,sendtype,dest,sendtag,recvbuf, recvcount recvtype source recvtag comm status ierr recvcount,recvtype,source,recvtag,comm,status,ierr)

用户通过指定传出(send)和接受(dest)方,数据种类,大小来完成数据传输。

2.2 如何减少数据传输量

网格被分配到3个CPU上(不同的颜色表示不同的CPU)

网格如何在CPU上分配是减少CPU间数据传输量的主要方法。网格的配分(partition)方法一般要满足如下原则

  • 各CPU的计算量(往往可以但不限于由CPU持有的单元,节点数来判断)大致相当

  • CPU间的共有节点(在你采用边单元的时候是共有边,当你采用面单元或FVM时是共有面)数要尽量小。

这是一个标准的图论(graph)优化问题,数学家们已经提供了不少优秀的开源软件。

Obtaining ParMETIS | Karypis Labglaros.dtc.umn.edu/gkhome/metis/parmetis/download

Static Mapping, Graph, Mesh and Hypergraph Partitioning, and Parallel and Sequential Sparse Matrix Ordering Packagewww.labri.fr/perso/pelegrin/scotch/

https://github.com/sandialabs/Zoltangithub.com/sandialabs/Zoltan

对于有限元软件的开发者(至少对我而言),有用的就好。

3. Don't reinvent the wheel!

分布式计算原理可说简单,但是其实装却是极其繁复。即使是要仅仅实现CPU间的多对多通信都要死掉不少脑细胞。更不要说考虑网格界面的滑动,单元的消失和生成,网格重新划分等等。好在经过几十年的大浪淘沙,当下已有很优秀的开源软件可用。如果倒回二十年前就没有这么轻松了。

3.1 Trilinos

GitHub - trilinos/Trilinos: Primary repository for the Trilinos Projectgithub.com/trilinos/Trilinos

Trilinos下属的 Tpetra软件(用于替代旧式的Epetra: Linear Algebra Services Package软件)实装了分布式数据管理。

Tpetra使用一个Map类来管理CPU间的通信

Tpetra::map<> mymap(numGlobalEntries, numLocalEntries, indexBase, comm);
Tpetra::vector<> x(mymap);

用户可以通过指定一个各CPU的大致的数据量来定义一个Map类,然后通过该map类定义的分布式数据(vector,matrix)都会置于map的管理下,原则上所有的CPU间的通信都不要用户来具体操作。

Tpetra提供了数种map类和数据类型(上面的Map,vector类都含有数个template类型),以便用户对于计算过程做细小粒度的控制。

3.2 petsc

https://gitlab.com/petsc/petscgitlab.com/petsc/petsc

使用petsc来生成一维数组

Vec v;
VecCreate(comm, &v);
VecSetSizes(v,m,M);

用户需要指定数组全体的长度M或/和在本CPU上的长度m。对于二维数组

Mat A;
MatCreate(comm, &A);
MatSetSizes(A,m,n,M,N);

用户需要指定矩阵全体的长度M,N或/和在本CPU上的长度m,n。这里用户指定的长度可以通过petsc优化处理(往往使用上面提到的开源软件metis, scotch)。数据通信也完全交给petsc来处理。

petsc没有提供像trilinos那样多的细节管理。但是使用起来也相对简单。特别是对只是熟悉Fortran,c这样的结构化程序的用户而言。Trilinos则用到了非常多的现代c  功能。

理论科普HPC非线性
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2022-10-02
最近编辑:2年前
hillyuan
力学博士,仿真软件开发者
获赞 139粉丝 12文章 28课程 0
点赞
收藏
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈