OpenSHMEM 介绍和使用指南
什么是 OpenSHMEM?
OpenSHMEM 是一个用于并行计算的标准化 API,它提供了一种分区全局地址空间 (PGAS) 编程模型。OpenSHMEM 最初由 Cray 公司开发,后来成为一个开源项目,旨在为高性能计算提供高效的通信接口。
OpenSHMEM 的主要特点包括:
- 基于单向通信(无需握手)
- 支持远程内存访问(RMA)
- 提供集体操作和原子操作
- 专为高性能计算设计
OpenSHMEM 的核心概念
- PE (Processing Element):执行单元,类似于 MPI 中的进程
- Symmetric Data:在所有 PE 上具有相同名称和布局的数据
- Remote Memory Access:直接访问远程 PE 的内存
- Active Messages:将数据与处理程序一起发送
安装 OpenSHMEM
OpenSHMEM 有多种实现,以下是几种常见的:
-
Open MPI 的 OpenSHMEM 实现:
sudo apt install openmpi-bin libopenmpi-dev
-
Sandia OpenSHMEM (SOS):
从 https://github.com/Sandia-OpenSHMEM/SOS 获取源代码并编译 -
Cray OpenSHMEM:通常在 Cray 系统上预装
基本使用
简单的 OpenSHMEM 程序结构
#include <shmem.h>
#include <stdio.h>
int main(void) {
shmem_init();
int mype = shmem_my_pe(); // 获取当前 PE 的 ID
int npes = shmem_n_pes(); // 获取 PE 的总数
printf("Hello from PE %d of %d\n", mype, npes);
shmem_finalize();
return 0;
}
编译和运行
使用 Open MPI 的实现:
oshcc -o hello hello.c
oshrun -np 4 ./hello
常用 OpenSHMEM 操作
1. 对称内存分配
int* shared_var = (int*)shmem_malloc(sizeof(int));
*shared_var = 0;
shmem_barrier_all(); // 确保所有 PE 都完成了初始化
2. 远程内存访问 (Put/Get)
// PE 0 发送数据到 PE 1
if (mype == 0) {
int value = 42;
shmem_int_put(shared_var, &value, 1, 1); // 将 value 放入 PE 1 的 shared_var
}
shmem_barrier_all();
if (mype == 1) {
printf("PE 1 received: %d\n", *shared_var);
}
3. 原子操作
// 所有 PE 对一个共享变量进行原子加
shmem_int_atomic_add(shared_var, mype+1, 0); // 在 PE 0 的 shared_var 上加上 mype+1
shmem_barrier_all();
if (mype == 0) {
printf("Total sum: %d\n", *shared_var); // 应该输出 1+2+...+npes
}
4. 集体操作
int local_data = mype + 1;
int global_sum;
shmem_int_sum_to_all(&global_sum, &local_data, 1, 0, 0, npes, NULL);
printf("PE %d: global sum is %d\n", mype, global_sum); // 所有 PE 输出相同的结果
高级特性
-
非阻塞操作:
shmem_put_nbi(dest, src, len, pe); // 非阻塞 put shmem_quiet(); // 等待所有非阻塞操作完成
-
信号量:
long* lock = shmem_malloc(sizeof(long)); shmem_set_lock(lock); // 获取锁 // 临界区代码 shmem_clear_lock(lock); // 释放锁
-
远程原子操作:
int fetched = shmem_int_fetch_add(remote_var, 1, pe); // 原子加并返回旧值
性能优化建议
- 尽量减少同步操作(如
shmem_barrier_all
) - 使用非阻塞操作和批量操作
- 合理利用对称内存布局
- 根据网络特性调整通信粒度
资源
OpenSHMEM 特别适合需要频繁进行远程内存访问的应用程序,如图算法、稀疏线性代数和某些类型的机器学习算法。