MPI Profile

MPI程序开发者需要了解应用程序运行过程中的性能指标、通信模式以优化程序的性能,衍生出了相应的分析工具。MPI标准最初提供了Profile接口PMPI,分析工具可以通过PMPI接口拦截MPI调用,从而分析应用程序对不同MPI接口的调用次数与消耗的时间。然而使用PMPI并不能反映与追踪MPI内部实现的行为(如集合通信算法),为了弥补这一点,MPI 3.0标准引入了MPI Tool接口(MPI_T)。分析工具可以借助其查询MPI的内部信息。

参考的文章:

The MPI Tool Interfaces: Past, Present, and Future—Capabilities and Prospects

会议:The International Parallel Tools Workshop

DOI: 10.1007/978-3-030-66057-4_3

PMPI–MPI Profiling Interface

PMPI的实现如下图,MPI通常会将MPI_定义为弱符号,将PMPI_定义为弱符号,在MPI库中调用它们会产生同样的效果。不过分析工具可以重新定义MPI_函数,增加需要的预处理、后处理内容,并在其中调用PMPI_函数从而完成原有功能。由于MPI库中的MPI_函数被定义为弱符号,因此可以被工具中新定义的函数覆盖。常用的MPI Profile工具TAU、mpiP、Score-P、Vampir等都有通过这一方式实现。

image-20230920204139050

除了供上述Profile工具使用,PMPI也可以用到MPI调用正确性检测、快速改变单一MPI调用的实现(如通过调用点对点通信重新实现一个集合通信操作而不用在MPI库中进行更改)等方向上。

PMPI存在一些缺点,如无法深入刨析MPI调用内部的情况、它的设计模式导致同一时间只有一个基于PMPI的工具能够运行。文献[1]中的作者提出了QMPI,可以将不同工具基于PMPI实现的函数存在一张表中,动态选择。

MPI_T–MPI Tools Information Interface

正如之前多次提到的,PMPI实现中,MPI内部的行为仍然是一个黑盒子,我们只能在接口层面获取到应用程序的行为。这导致用户很难做进一步的优化。因此在MPI 3.0中产生了MPI_T。使用MPI_T,MPI库可以公开各种与性能或准确性相关的信息,如配置控制信息、性能信息、调试信息、应用程序调用相关信息。

3.0版本的MPI_T仅是一个查询接口,用户或分析工具可以从MPI内部获取信息,通过查询MPI_T接口能在运行时获得性能(P, Performance)、控制(C, Control)、变量目录(Variable Categories)相关数据与信息。

MPI_T的一个优点是具有很好的灵活性,不过由于它给出的信息大都基于文本,对其使用需要借助开发人员人工干预。

可以通过以下程序查询可用的变量 (related issue):

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
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void main(int argc, char* argv[]) {

int rank, size;

MPI_Init(&argc, &argv);

int provided;
MPI_T_init_thread(MPI_THREAD_SINGLE, &provided);

int num;
MPI_T_pvar_get_num(&num);
printf("%d performance variables\n", num);

char name[256], desc[256];
int len= (int) (sizeof(name)/ sizeof(name[0]));
int namelen, desclen, verbosity, varclass, bind, rdonly, cont, atomic, scope;
MPI_Datatype dt;
MPI_T_enum et;
for(int i= 0; i< num; ++i) {
int err= MPI_T_pvar_get_info(i, name, &namelen, &verbosity, &varclass, &dt, &et, desc, &desclen, &bind, &rdonly, &cont, &atomic);
name[len- 1]= '\0'; desc[len- 1]= '\0';
printf("%2d: ", i);
switch(err) {
case MPI_SUCCESS:
printf("%s (%d/ %d) - desc: \"%s\" (%d/%d)\n", name, namelen, len- 1, desc, desclen, len- 1);
break;
case MPI_T_ERR_NOT_INITIALIZED:
printf("The MPI tool information interface is not initialized(%d).\n", err);
break;
case MPI_T_ERR_INVALID_INDEX:
printf("Index is invalid or has been deleted(%d).\n", err);
break;
case MPI_T_ERR_INVALID:
printf("Performance variable is invalid(%d).\n", err);
break;
default:
printf("Unknown error!\n");
break;
}
}


MPI_T_cvar_get_num(&num);
printf("%d control variables\n", num);

for(int i= 0; i< num; ++i) {
int err= MPI_T_cvar_get_info(i, name, &namelen, &verbosity, &dt, &et, desc, &desclen, &bind, &scope);
name[len- 1]= '\0'; desc[len- 1]= '\0';
printf("%2d: ", i);
switch(err) {
case MPI_SUCCESS:
printf("%s (%d/ %d) - desc: \"%s\" (%d/%d)\n", name, namelen, len- 1, desc, desclen, len- 1);
break;
case MPI_T_ERR_NOT_INITIALIZED:
printf("The MPI tool information interface is not initialized(%d).\n", err);
break;
case MPI_T_ERR_INVALID_INDEX:
printf("Index is invalid or has been deleted(%d).\n", err);
break;
case MPI_T_ERR_INVALID:
printf("Control variable is invalid(%d).\n", err);
break;
default:
printf("Unknown error!\n");
break;
}
}

MPI_T_finalize();

MPI_Finalize();
}

Control Variables

Control Variables(cvar)为用户公开了一系列变量,初衷是用户可以通过设置这些变量影响MPI实现在执行过程中的行为,不过目前版本应该也都只支持查询。以Open MPI为例,其组件注册的MCA参数大都作为cvar。通过对cvar的查询和更改,能够为一些工具实现新功能提供支持,如对于一些参数调优工具,原本需要多次运行程序遍历参数空间选出最优参数,借助cvar即可在一次运行中完成这一操作。

Performance Variables

Performance Variables(pvar)能够提供关于MPI库内部状态变化的信息,如发送消息的数据包数量、阻塞操作的运行时间或内存占用。

image-20230920215553813

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
20 performance variables
0: ���� (31/ 255) - desc: "" (1/255)
1: pml_monitoring_flush (21/ 255) - desc: "" (1/255)
2: pml_monitoring_messa (21/ 255) - desc: "" (1/255)
3: pml_monitoring_messa (21/ 255) - desc: "" (1/255)
4: osc_monitoring_messa (21/ 255) - desc: "" (1/255)
5: osc_monitoring_messa (21/ 255) - desc: "" (1/255)
6: osc_monitoring_messa (21/ 255) - desc: "" (1/255)
7: osc_monitoring_messa (21/ 255) - desc: "" (1/255)
8: coll_monitoring_mess (21/ 255) - desc: "" (1/255)
9: coll_monitoring_mess (21/ 255) - desc: "" (1/255)
10: coll_monitoring_o2a_ (21/ 255) - desc: "" (1/255)
11: coll_monitoring_o2a_ (21/ 255) - desc: "" (1/255)
12: coll_monitoring_a2o_ (21/ 255) - desc: "" (1/255)
13: coll_monitoring_a2o_ (21/ 255) - desc: "" (1/255)
14: coll_monitoring_a2a_ (21/ 255) - desc: "" (1/255)
15: coll_monitoring_a2a_ (21/ 255) - desc: "" (1/255)
16: Performance variable is invalid(72).
17: Performance variable is invalid(72).
18: osc_rdma_put_retry_c (21/ 255) - desc: "" (1/255)
19: osc_rdma_get_retry_c (21/ 255) - desc: "" (1/255)

Reference


  1. M. Schulz, M.-A. Hermanns, M. Knobloch, K. Mohror, N.T. Hjelm, B. Elis, K. Kraljic, D. Yang, The MPI Tool Interfaces: Past, Present, and Future—Capabilities and Prospects, in: H. Mix, C. Niethammer, H. Zhou, W.E. Nagel, M.M. Resch (Eds.), Tools for High Performance Computing 2018 / 2019, Springer International Publishing, Cham, 2021: pp. 55–83. https://doi.org/10.1007/978-3-030-66057-4_3. ↩︎