使用混合模型OpenSHMEM + CUDA及OpenSHMEM应用程序性能分析
在高性能计算领域,OpenSHMEM与CUDA的混合模型以及OpenSHMEM应用程序的性能分析是重要的研究方向。下面将详细介绍相关内容。
同步集合操作函数实现
为了替代MPI集合操作,实现了一系列SHMEM集合操作函数,使用C++模板提供更友好的API,具体函数如下:
template<class T>
void gather ( vector<T>& gvec , T *val , int root , shmem_team_t tm , long *pSyncBar ) ;
template<class T>
void allgather ( vector<T>& gvec , T *val , shmem_team_t tm , long *pSyncBar ) ;
template<class T>
T reduction_sum (T val , int root , shmem_team_t tm , long *pSyncBar ) ;
template<class T>
T reduction_sum_all (T val , shmem_team_t tm , long *pSyncBar ) ;
template<class T>
T prefixscan (T val , shmem_team_t tm , long *pSyncBar ) ;
template<class T>
T exprefixscan (T val , shmem_team_t tm , long *pSyncBar ) ;
template<class T>
void bcast (T *buf , int count , int root , shmem_team_t tm , long *pSyncBar ) ;
当 shmem_team_t 等于 SHMEM_TEAM_WORLD 时,使用全局集合函数。
各集合操作的实现方式
- Gather操作 :通常
shmem_put比shmem_get更快,但基于put的收集操作要求团队中的每个处理元素(PE)在根PE上有特定位置来存放其值,这需要根PE有对称空间,而该对称空间无法以团队为基础进行shmalloc分配。因此,采用非阻塞的shmem_get到本地非对称向量,避免了此问题。所有操作依赖于shmem_translate_pe将团队PE编号转换为全局PE编号,该函数的快速版本对所有团队集合实现都很重要。 - Reduction操作 :使用基于树的归约方法。处理器排列成k叉树,k在编译时指定。结果在树中向上求和,每个PE累积k个子节点的值。每个PE使用
shmem_int_wait函数在计数器上阻塞,该计数器由每个子节点原子递增,直到计数器达到k。最终结果在树的根节点累积。经过测试,选择二叉树避免使用原子递增,速度更快。在广播结果时,节点数为16时基于树的广播更快,节点数较少时屏障更快。 - Broadcast操作 :团队广播使用与归约最后阶段相同的算法,值从根节点通过二叉树向下传递到叶子节点。
- Prefix Scan操作 :使用传统的上扫和下扫阶段实现。同步主要是点对点的,但需要几个屏障来确保标志值正确重置为0。为支持非2的幂次方大小的团队,扫描内部使用团队将扫描拆分为2的幂次方大小的子扫描,然后对子扫描结果进行扫描,并将结果广播回子团队。
性能测试
- 硬件平台 :在橡树岭国家实验室的Cray XK7 Titan系统上运行基准测试,该系统的Cray消息传递工具包提供了上述团队函数。
- 集合操作的扩展性 :将基于SHMEM实现的集合操作性能与原生MPI实现进行比较。原生高度优化的MPI集合操作在归约和全收集操作上更快,但SHMEM的收集操作比MPI实现显著更快,尽管该收集操作无法与其他计算重叠,只是向所有进程发出非阻塞单边
get操作,然后执行屏障以防止过早覆盖对称数据。 - 可移植团队实现 :为将代码移植到其他系统,使用OpenMPI 1.8.2编译器在商品Linux集群上测试可移植团队API层。Cray团队屏障操作在32个核心(2个节点)时出现重大减速,然后再次加速;基于树的屏障在16个节点之前表现良好,之后扩展性较差。Cray SHMEM的拆分实现在低核心数时较慢,但扩展性更好;基于OpenSHMEM的拆分使用全收集集合操作,在高核心数时扩展性较差。总体而言,可移植团队实现在中等核心数时可用,要扩展到大规模核心数需要更多测试和优化。
- 基准测试扩展性 :SHOC基准测试结果以吞吐量速率报告。在尴尬并行(EP)基准测试中,SHMEM通信仅用于并行数据库的结果聚合,通信时间不包含在基准测试结果中,因此EP基准测试使用MPI或SHMEM运行结果相同。四个TP基准测试在CUDA内核外使用SHOC进行通信,在最多32个节点上运行基准测试时,使用OpenSHMEM未观察到运行时间的显著变化。这表明SHMEM可有效用作通信层,执行与MPI相同的功能,但从MPI迁移到SHMEM进行混合编程时,同步集合操作可用时最为自然。当前实现层在低核心数时性能良好,但要扩展到大规模作业需要更具扩展性的实现和底层优化。
下面通过一个mermaid流程图展示集合操作的整体流程:
graph LR
A[开始] --> B[选择集合操作类型]
B --> C{是否为Gather操作}
C -- 是 --> D[使用非阻塞shmem_get]
C -- 否 --> E{是否为Reduction操作}
E -- 是 --> F[基于树的归约]
E -- 否 --> G{是否为Broadcast操作}
G -- 是 --> H[二叉树广播]
G -- 否 --> I{是否为Prefix Scan操作}
I -- 是 --> J[上扫和下扫阶段]
I -- 否 --> K[其他操作]
D --> L[结束]
F --> L
H --> L
J --> L
K --> L
OpenSHMEM应用程序性能分析工具
在开发高性能OpenSHMEM应用程序时,深入了解软件执行情况很重要,但在生产环境中收集性能指标存在诸多障碍。大多数OpenSHMEM性能分析器依赖PSHMEM接口,但该接口可选且常不可用。下面介绍一种即使PSHMEM不可用时也能生成OpenSHMEM应用程序直接测量性能分析的工具。
工具概述
该工具集成在TAU性能系统中,可对动态链接和静态链接的应用程序二进制文件进行操作,不需要调试符号,且不受编译器优化级别影响。它使用自动生成的包装库拦截OpenSHMEM API调用,以最小的开销收集性能指标,动态链接的应用程序无需修改应用程序二进制文件即可使用该工具。
实现方法
- Symbol Wrapping :对于OpenSHMEM标准中的每个例程,PSHMEM提供一个名称略有不同的类似例程。使用程序链接器的符号包装功能实现相同效果,几乎所有程序链接器都支持
-wrap foosym命令行选项来包装符号foosym。未定义的foosym引用将解析为__wrap_foosym,未定义的__real_foosym引用将解析为foosym。在应用程序对象文件链接成可执行文件时,通过大多数链接器支持的@argfile语法将每个OpenSHMEM API调用的-wrap标志传递给链接器。此方法适用于静态链接的应用程序和静态链接到OpenSHMEM实现的动态链接应用程序,但动态链接到libopenshmem.so的应用程序应使用库预加载。 - Library Preloading :符号包装是一种强大且低开销的包装OpenSHMEM API的方法,但在生产环境中用户可能无法重新链接应用程序。因此,使用库预加载动态实现链接器的静态功能。通过设置
LD_PRELOAD环境变量,在搜索列表前端插入动态符号包装器,将未定义的foosym引用解析为__wrap_foosym,未定义的__real_foosym引用解析为foosym。这要求应用程序动态链接到OpenSHMEM实现库。
操作步骤总结
- Symbol Wrapping操作步骤 :
- 解析OpenSHMEM头文件,确定所有API函数。
- 为每个API函数生成唯一的包装函数。
- 在链接应用程序对象文件时,通过
@argfile语法将每个OpenSHMEM API调用的-wrap标志传递给链接器。
- Library Preloading操作步骤 :
- 确保应用程序动态链接到OpenSHMEM实现库。
- 设置
LD_PRELOAD环境变量,将动态符号包装器库添加到搜索列表前端。
通过以下表格对比两种方法的特点:
| 方法 | 适用场景 | 优点 | 缺点 |
| — | — | — | — |
| Symbol Wrapping | 静态链接应用程序和静态链接到OpenSHMEM实现的动态链接应用程序 | 低开销,可直接在链接时拦截API调用 | 需要重新链接应用程序 |
| Library Preloading | 动态链接到 libopenshmem.so 的应用程序 | 无需重新链接应用程序 | 依赖环境变量设置 |
下面是一个mermaid流程图展示工具的整体工作流程:
graph LR
A[开始] --> B{应用程序链接类型}
B -- 静态链接或静态链接到OpenSHMEM实现的动态链接 --> C[Symbol Wrapping]
B -- 动态链接到libopenshmem.so --> D[Library Preloading]
C --> E[拦截OpenSHMEM API调用]
D --> E
E --> F[使用TAU收集性能指标]
F --> G[结束]
综上所述,OpenSHMEM与CUDA的混合模型在高性能计算中具有重要应用,通过实现集合操作函数和优化其实现方式可提高性能。同时,OpenSHMEM应用程序性能分析工具为开发人员在生产环境中收集性能指标提供了有效解决方案,通过符号包装和库预加载两种方法可适应不同的应用程序链接类型。未来,还需要进一步优化这些实现以支持更大规模的作业。
使用混合模型OpenSHMEM + CUDA及OpenSHMEM应用程序性能分析
深入探讨集合操作实现细节
在前面提到的集合操作中,每种操作都有其独特的实现细节和优势。下面我们进一步分析这些操作在不同场景下的表现。
-
Gather操作的优势与挑战 :SHMEM的Gather操作比MPI实现显著更快,这一结果令人意外。其原因在于采用了非阻塞的
shmem_get操作,避免了使用shmem_put可能带来的对称空间分配问题。但这种操作方式也存在挑战,由于无法与其他计算重叠,可能在某些复杂计算场景下影响整体性能。例如,在大规模数据收集时,如果其他计算任务不能与Gather操作并行执行,会导致计算资源的闲置。 -
Reduction操作的优化选择 :在Reduction操作中,选择二叉树结构避免使用原子递增,是基于性能测试的结果。这种选择不仅提高了计算速度,还减少了原子操作带来的开销。但在不同节点数的情况下,广播结果的方式需要根据实际情况进行调整。例如,当节点数较少时,使用屏障方式可以更快地完成广播;而当节点数达到16时,基于树的广播方式则更为高效。
-
Broadcast操作的稳定性 :团队广播使用与归约最后阶段相同的算法,这种一致性使得代码实现更加简洁,同时也保证了操作的稳定性。通过二叉树结构将值从根节点传递到叶子节点,能够有效地减少通信开销,提高广播效率。
-
Prefix Scan操作的灵活性 :Prefix Scan操作通过将扫描拆分为2的幂次方大小的子扫描,能够支持非2的幂次方大小的团队。这种灵活性使得该操作在不同规模的团队中都能正常工作,并且通过上扫和下扫阶段的结合,保证了计算结果的准确性。
为了更直观地展示这些操作的特点,我们可以通过以下表格进行对比:
| 操作类型 | 实现方式 | 优势 | 挑战 |
| — | — | — | — |
| Gather | 非阻塞 shmem_get | 避免对称空间分配问题,速度快 | 无法与其他计算重叠 |
| Reduction | 二叉树归约 | 避免原子递增,性能优 | 广播方式需根据节点数调整 |
| Broadcast | 二叉树广播 | 代码简洁,稳定性高 | |
| Prefix Scan | 上扫和下扫阶段,子扫描拆分 | 支持非2的幂次方团队 | 需要屏障确保标志值重置 |
性能测试结果分析
在性能测试中,我们对比了基于SHMEM实现的集合操作与原生MPI实现的性能。这些结果对于选择合适的编程模型和优化策略具有重要意义。
-
集合操作扩展性的差异 :从测试结果可以看出,原生高度优化的MPI集合操作在归约和全收集操作上表现出色,而SHMEM的Gather操作则具有明显优势。这种差异主要是由于两种编程模型的设计理念和实现方式不同。MPI更注重整体的优化和高效通信,而SHMEM则在某些操作上通过独特的实现方式提高了性能。
-
可移植团队实现的局限性 :可移植团队实现在中等核心数时可用,但要扩展到大规模核心数还需要更多的测试和优化。Cray团队屏障操作和基于树的屏障在不同节点数下的表现差异,以及Cray SHMEM和OpenSHMEM拆分实现的不同扩展性,都表明在不同硬件平台和节点数下,需要选择合适的团队实现方式。
为了更好地理解这些性能差异,我们可以通过以下mermaid流程图展示集合操作扩展性的对比:
graph LR
A[集合操作] --> B{编程模型}
B -- SHMEM --> C[Gather操作]
B -- SHMEM --> D[Reduction操作]
B -- SHMEM --> E[Broadcast操作]
B -- SHMEM --> F[Prefix Scan操作]
B -- MPI --> G[Gather操作]
B -- MPI --> H[Reduction操作]
B -- MPI --> I[Broadcast操作]
B -- MPI --> J[Prefix Scan操作]
C --> K[扩展性分析]
D --> K
E --> K
F --> K
G --> K
H --> K
I --> K
J --> K
K --> L[性能对比结果]
OpenSHMEM应用程序性能分析工具的应用与优化
OpenSHMEM应用程序性能分析工具通过符号包装和库预加载两种方法,为开发人员在生产环境中收集性能指标提供了有效解决方案。下面我们进一步探讨这两种方法的应用场景和优化策略。
-
Symbol Wrapping的应用场景 :Symbol Wrapping适用于静态链接的应用程序和静态链接到OpenSHMEM实现的动态链接应用程序。这种方法的优点是低开销,能够直接在链接时拦截API调用。但需要重新链接应用程序,这在某些生产环境中可能会带来不便。例如,在大型项目中,重新链接可能会导致编译时间过长,影响开发效率。
-
Library Preloading的优化策略 :Library Preloading适用于动态链接到
libopenshmem.so的应用程序,无需重新链接应用程序。但这种方法依赖环境变量设置,如果环境变量设置不当,可能会导致性能分析工具无法正常工作。为了避免这种情况,开发人员可以在脚本中自动设置LD_PRELOAD环境变量,确保工具的正常运行。
为了更好地应用这两种方法,我们可以按照以下步骤进行操作:
1. 选择合适的方法 :根据应用程序的链接类型,选择Symbol Wrapping或Library Preloading方法。
2. 配置环境 :如果使用Library Preloading方法,确保正确设置 LD_PRELOAD 环境变量。
3. 运行性能分析 :使用TAU性能系统收集性能指标,并进行分析。
通过以上步骤,开发人员可以有效地利用性能分析工具,深入了解OpenSHMEM应用程序的性能瓶颈,从而进行针对性的优化。
综上所述,OpenSHMEM与CUDA的混合模型在高性能计算中具有重要的应用价值,通过优化集合操作的实现和使用性能分析工具,可以进一步提高计算性能和开发效率。未来,随着硬件技术的不断发展和编程模型的不断完善,我们有望在更大规模的作业中实现更高效的计算。
超级会员免费看

1383

被折叠的 条评论
为什么被折叠?



