运用 Metis 工具分割非结构网格和结构网格用于并行计算
Question
Metis 和 ParMetis 的区别
Graph 和 Mesh 的区别
运用 Metis 划分结构网格
运用 Metis 划分非结构网格
Introduction
“Metis” was a titaness in Greek mythology and presided over all wisdom and knowledge.
Application
graph and mesh partitioning
compute fill-reducing orderings of sparse matrices
solving optimization problems arising in numerous areas
Algorithm
multilevel k-way partitioning
multilevel recursive bisection
Version
Implement
Stand-alone Programs + File – Graph/Mesh/Weight
API – C/C++/Fortran
fill-reducing orderings
一种稀疏矩阵排列方法,旨在减少矩阵分解过程中的 fill-in 元素
Algorithm
Graph
METIS 算法基于 multilevel graph partitioning paradigm
multilevel paradigm 包含三个 Phase
graph coarsening: 图形粗化
initial partitioning: 初始化分割
graph uncoarsening: 图形细化
multilevel recursive bisection
multilevel k-way partitioning
minimize the resulting subdomain connectivity graph
enforce contiguous partitions
minimize alternative objectives
METIS 算法通过将各点添加权重矢量从而均衡不同阶段和不同物理场中每个域的计算负载和存储资源
Mesh
METIS 通过 mpmetis
程序分割有限元或有限体积网格 (Mesh)
程序 m2gmetis
首先将网格转换为 Graph
Dual Graph: 将 Mesh Element 转换为 Graph Vertex
Nodal Graph: 将 Mesh Node 转换为 Graph Vertex
调用 Graph partitioning API 分割 Graph
还原网格
METIS 未直接提供网格的多约束分割功能,因此需要通过 m2gmetis
间接实现
Heterogeneous
异构计算
Data Structrue
Graph Data
Graph
mindmap
v1((1))
v2((2))
v3((3))
v4((5))
Graph file
1 2 3 4 5 6 7 11 111 3 | (n m fmt ncon) 2 1 2 0 5 1 3 2 2 1 | (s w1 w2 .. w_ncon v1 e1 v2 e2 .. vk ek) ... | ... n_vert, n_edge, vert_size/w_vert/w_edge, nw_vert vert_size, w_vert, conn_vert, w_edge
n = 7
number of vertices
m = 11
number of edges
fmt = 111
whether set vertex sizes, vertex weights, and edge weights
ncon = 3
number of vertex weights
s = 2
vertex size, amount of data that needs to be sent for vertex
w = (1 2 0)
weight of vertex
v e = (5 1) (3 2) (2 1)
(adjacent vertex, edge weight)
API Graph CSR (Compressed storage format)
1 2 3 4 5 6 7 1 --- 2 --- 3 --- 4 | | | | 5 --- 6 --- 7 --- 8 index 1 2 3 4 5 ... 8 xadj 1 3 6 9 11 ... 19 21 adjncy 2 5 1 3 6 2 4 7 3 8 1 6 ... 4 7
xadj
index of adjacency array for each vertex
xadj(n+1) - 1
is last index of adjacency array
adjncy(2m)
array of adjacency vertices of each vertex
vwgt(n*ncon)
weights of the vertices (same weight => NULL)
adjwgt(2m)
weights of the edges (same weight => NULL)
Mesh Data
Mesh File
1 2 3 7 2 | (ne ncon) 3 1 1 3 4 2 | (w1 w2 .. w_ncon n1 n2 ..) ...
ne = 7
number of elements
ncon = 2
optinal , number of element weights
w = (3 1)
element weight
n = (1 3 4 2)
element node array (unordered)
API mesh format
1 2 3 4 5 6 7 1 --- 2 --- 3 --- 4 | I | II | III | 5 --- 6 --- 7 --- 8 index 1 2 3 eptr 1 5 9 13 eind 1 2 5 6 2 3 6 7 3 4 7 8
Mesh Data Structrue
eptr
index of eind
array for each element
eind
list of element nodes (unordered)
Implementation
Multi-Block Structrual Mesh
Strategies: top-down
bottom-up
Communication Cost
number of communication (edge cuts)
volume of communication
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 less edge cuts * -- * -- * -- * -- * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * -- * -- * -- * -- * small volume of communication * ------- * ------- * | | | | | | | | | * ------- * ------- * | | | | | | | | | * ------- * ------- *
Group and merge Small Blocks
Method
REB
Recursive Edge Bisection
IF
Integer Factorization
IF
Partition (N = 7, 73, 16, 27)
Error Accumulation of IF
Block Partition
volume of single block V s = V × 1 n p ( 1 ± ε ) volume of other block V u = V − V s n p − 1 = V × 1 n p ( 1 ∓ ε n p − 1 ) \begin{align}
& \text{volume of single block} \qquad
V_s = V \times \frac{1}{n_p} (1 \pm \varepsilon) \\
& \text{volume of other block} \qquad
V_u = \frac{V - V_s}{n_p -1}
= V \times \frac{1}{n_p} (1 \mp \frac{\varepsilon}{n_p - 1}) \\
\end{align} volume of single block V s = V × n p 1 ( 1 ± ε ) volume of other block V u = n p − 1 V − V s = V × n p 1 ( 1 ∓ n p − 1 ε )
Load Imbalance
For single block ( V a v e − V s ) 2 = V a v e 2 × ε 2 For other block ( V a v e − V u ) 2 = V a v e 2 × ε 2 / ( n p − 1 ) 2 Variance S 2 = 1 n p ( ( V a v e − V s ) 2 + ( n p − 1 ) ( V a v e − V u ) 2 ) Deviation S = V a v e ε n p − 1 Imbalance S V a v e = ε n p − 1 \begin{align}
& \text{For single block} \qquad
(V_{ave} - V_s)^2 = V_{ave}^2 \times \varepsilon^2 \\
& \text{For other block} \qquad
(V_{ave} - V_u)^2 = V_{ave}^2 \times \varepsilon^2/(n_p-1)^2 \\
& \text{Variance} \qquad
S^2 = \frac{1}{n_p} \left( (V_{ave} - V_s)^2 +
(n_p - 1) (V_{ave} - V_u)^2 \right) \\
& \text{Deviation} \qquad
S = V_{ave} \frac{\varepsilon}{\sqrt{n_p - 1}} \\
& \text{Imbalance} \qquad
\frac{S}{V_{ave}} = \frac{\varepsilon}{\sqrt{n_p - 1}} \\
\end{align} For single block ( V a v e − V s ) 2 = V a v e 2 × ε 2 For other block ( V a v e − V u ) 2 = V a v e 2 × ε 2 / ( n p − 1 ) 2 Variance S 2 = n p 1 ( ( V a v e − V s ) 2 + ( n p − 1 ) ( V a v e − V u ) 2 ) Deviation S = V a v e n p − 1 ε Imbalance V a v e S = n p − 1 ε
Unstructural Mesh
Program
Fortran 中无法直接调用 metis.h
文件,需要编写接口,具体可参考
metis | JCSDA
METIS for fpm | gnikit
fmetis | ivan-pi
Formetis | SWIG-Fortran
Compile
Install
安装 Metis
1 2 3 4 5 6 7 8 9 10 11 12 git clone https://github.com/KarypisLab/METIS.git git clone https://github.com/KarypisLab/GKlib.git wget https://github.com/KarypisLab/METIS/archive/refs/tags/v5.1.1-DistDGL-v0.5.tar.gz cd GKlibmake config prefix=$HOME /local/metis/metis-5.2.1 CONFIG_FLAGS='-D BUILD_SHARED_LIBS=ON -D CMAKE_INSTALL_PREFIX=' $HOME '/local/metis/metis-5.2.1' make && make install cd METISmake config shared=1 cc=gcc prefix=$HOME /local/metis/metis-5.2.1 make install
添加环境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 proc ModulesHelp {} { puts stderr "Program: METIS $::version" puts stderr "Description: Karypis -- A set of serial programs for partitioning graphs, " puts stderr " partitioning finite element meshes, and producing " puts stderr " fill reducing orderings for sparse matrices. " puts stderr "Github: https://github.com/KarypisLab/METIS" puts stderr {} } set version 5.2.1set prefix $HOME /local/metis/metis-$version module-whatis "METIS -- Graphs and mesh partition program" setenv METIS_HOME $prefix setenv METIS_INCLUDE $prefix /include setenv METIS_LIB $prefix /lib prepend-path PATH $prefix /bin prepend-path LD_LIBRARY_PATH $prefix /lib
Make
Makefile
CMake
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 set (METIS_ROOT ${PROJECT_SOURCE_DIR} /ext/METIS-5.2 .1 )find_path ( METIS_INCLUDE_PATH NAMES metis.h PATHS ${METIS_ROOT} /include ) find_library ( METIS_LIBRARY NAMES metis PATHS ${METIS_ROOT} /lib NO_DEFAULT_PATH ) if (METIS_INCLUDE_PATH AND METIS_LIBRARY) set (METIS_FOUND TRUE ) set (METIS_LIBRARY ${METIS_LIBRARY} ) set (METIS_INCLUDE_PATH ${METIS_INCLUDE_PATH} ) else () set (METIS_FOUND FALSE ) endif ()set (GKLIB_ROOT ${PROJECT_SOURCE_DIR} /ext/METIS-5.2 .1 )find_path ( GKLIB_INCLUDE_PATH NAMES GKlib.h PATHS ${GKLIB_ROOT} /include ) find_library ( GKLIB_LIBRARY NAMES GKlib PATHS ${GKLIB_ROOT} /lib NO_DEFAULT_PATH ) if (GKLIB_INCLUDE_PATH AND GKLIB_LIBRARY) set (GKLIB_FOUND TRUE ) set (GKLIB_LIBRARY ${GKLIB_LIBRARY} ) set (GKLIB_INCLUDE_PATH ${GKLIB_INCLUDE_PATH} ) else () set (GKLIB_FOUND FALSE ) endif ()find_package (GKLIB REQUIRED)if (GKLIB_FOUND) include_directories (${GKLIB_INCLUDE_PATH} ) message (STATUS "GKLIB library: ${GKLIB_LIBRARY}" ) message (STATUS "GKLIB include: ${GKLIB_INCLUDE_PATH}" ) else () message (FATAL_ERROR "GKLib library not found" ) endif ()find_package (METIS REQUIRED)if (METIS_FOUND) include_directories (${METIS_INCLUDE_PATH} ) message (STATUS "METIS library: ${METIS_LIBRARY}" ) message (STATUS "METIS include: ${METIS_INCLUDE_PATH}" ) else () message (FATAL_ERROR "METIS library not found" ) endif ()
Linker Attention
注意 Cmake 中必须按照 METIS-GKLIB 顺序链接
1 target_link_libraries (${EXEC} ${METIS_LIBRARY} ${GKLIB_LIBRARY} )
Reference