20、Cray SHMEM 中的线程安全与上下文 - 域特性解析

Cray SHMEM线程安全与上下文域解析

Cray SHMEM 中的线程安全与上下文 - 域特性解析

在高性能计算(HPC)应用中,提高应用程序的并发性能、减少节点内通信开销以及提升可扩展性是至关重要的目标。为了实现这些目标,人们提出了多种多线程方案,本文将详细介绍 Cray SHMEM 中的线程安全(Thread - Safe)和上下文 - 域(Contexts - Domains)这两个特性。

1. 背景介绍

在 OpenSHMEM 应用中,传统的 shmem init 调用存在一定的局限性,它必须由发起该调用的线程执行,这严重限制了应用程序的整体并发性能。为了解决这个问题,Cray 公司提出了线程安全特性,同时 Intel 提出了上下文 - 域特性。

  • Cray SHMEM :Cray SHMEM 是 Cray 公司开发的特定于供应商的 OpenSHMEM 实现,它是 Cray 消息传递工具包(MPT)软件栈的一部分。该实现版本为 7.4.0,符合 OpenSHMEM 规范版本 1.3。除了支持标准的 OpenSHMEM 特性外,还提供了线程安全扩展、灵活的 PE 子集创建和管理、带信号的点对点 put 操作以及本地共享内存指针等功能,这些额外功能以 SHMEMX 为前缀的扩展形式提供。
  • 线程安全提案概述 :该提案旨在支持在 SHMEM 线程区域中调用 RMA 和 AMO 例程,但对在这些区域中使用 SHMEM 集合操作有一定限制。在线程安全的 OpenSHMEM 实现中,SHMEM 处理元素(PE)是一个可以多线程化的操作系统进程,对称堆是每个 PE 的资源,PE 的所有线程共享地址空间。相关的例程如下:
int shmemx_init_thread ( int required_threading_type );
int shmemx_query_thread ( void );
void shmemx_thread_register ( void );
void shmemx_thread_unregister ( void );
void shmemx_thread_quiet ( void );
void shmemx_thread_fence ( void );
- `shmemx_init_thread`:用于初始化 OpenSHMEM 资源,并指定应用程序的线程级别。
- `shmemx_query_thread`:用于查询应用程序当前使用的线程级别。
- `shmemx_thread_register`:任何要进行 OpenSHMEM 调用的线程都必须调用此函数进行注册,以便库将线程映射到网络资源。
- `shmemx_thread_quiet` 和 `shmemx_thread_fence`:用于进行内存排序操作,分别等待特定线程的所有未完成操作完成和对特定线程的通信进行排序。
  • 上下文 - 域提案概述 :Dinan 等人提出了上下文和域的新特性,允许程序员生成独立的通信流,该特性将消息注入资源与远程完成跟踪分离。相关的 OpenSHMEM 扩展如下:
typedef int shmem_ctx_t;
typedef int shmem_domain_t;
void shmemx_domain_create ( int thread_level, int num_domain, shmem_domain_t domain [] );
void shmemx_domain_destroy ( int num_domain, shmem_domain_t domain [] );
int shmemx_ctx_create ( shmem_domain_t domain, shmem_ctx_t *ctx );
void shmemx_ctx_destroy ( shmem_ctx_t ctx );
void shmemx_ctx_fence ( shmem_ctx_t ctx );
void shmemx_ctx_quiet ( shmem_ctx_t ctx );
void shmemx_sync ( int PE_start, int logPE_stride, int PE_size, long *pSync );
void shmemx_sync_all ( void );
- `shmemx_domain_create` 和 `shmemx_domain_destroy`:用于创建和销毁域。
- `shmemx_ctx_create` 和 `shmemx_ctx_destroy`:用于创建和销毁上下文。
- `shmemx_ctx_fence` 和 `shmemx_ctx_quiet`:用于进行上下文级别的内存排序操作。

线程和上下文是应用程序中的两个独立实体,任何线程都可以通过上下文句柄使用上下文对象。此外,还有上下文版本的 RMA 和 AMO 例程,这些例程有一个额外的 shmem_ctx_t 句柄参数,用于指定特定通信操作发生的上下文。

void shmemx_ctx_TYPE_p (TYPE *addr, TYPE value, int pe, shmem_ctx_t ctx);
void shmemx_ctx_TYPE_get (TYPE *dest, const TYPE *source, size_t nelems, int pe, shmem_ctx_t ctx);
void shmemx_TYPE_inc(TYPE *dest, int pe, shmem_ctx_t ctx);
2. 使用细节
  • 线程安全特性 :使用线程安全特性时,首先需要注册线程,然后使用现在已经线程安全的普通 RMA 和 AMO 例程,最后在使用完毕后注销线程并退出。
  • 上下文 - 域特性 :任何线程都可以创建域和上下文对象,并使这些对象对其他线程可见。任何线程都可以选择这些对象并用于基于上下文的通信,参与上下文和域对象创建或基于上下文的通信操作的线程无需注册。

线程安全 API 和上下文 - 域 API 可以在同一个应用程序中使用,但不能在同一个 SHMEM 线程区域中使用。即使是已注册的线程也可以使用上下文对象。

3. 实现细节
3.1 DMAPP 基础

Cray DMAPP(分布式共享内存应用)库是 Cray 公司开发的底层通信层,用于支持逻辑共享的分布式内存编程模型。它提供了进程间的远程内存访问(RMA)支持,有快速内存访问(FMA)和块传输引擎(BTE)两种 RMA 机制,FMA 适用于小数据量传输,BTE 适用于大数据量传输。

对于每个基于 Cray SHMEM 的应用程序进程,DMAPP 会创建一个本地通信域(CDM)实例,并获取一个 cdm 句柄用于后续引用。为了使用 FMA 和 BTE 机制,需要配置 FMA 和 BTE 描述符并将它们附加到 CDM 上。所有的通信操作都通过 CDM 进行,并且每个 PE 必须有一个唯一的 CDM。每个节点的 FMA 描述符数量有限,例如在 Cray 开发的 Aries RDMA 互连中,每个节点的 FMA 描述符数量固定为 120。

事件通知机制通过完成队列(CQ)实现,每个 CDM 有自己的 CQ,用于跟踪该 CDM 上的所有事件。根据 DMAPP 设计,CDM 与 FMA 描述符以及 CDM 与 CQ 之间存在一对一的关系。

3.2 线程安全实现细节

在单线程应用中,每个 PE 有自己的 CDM 和对应的 CQ。在多线程应用中,每个注册的线程会获得自己的 CDM 和对应的 CQ,只有注册的线程才能进行 OpenSHMEM 调用。

如果注册的线程数量超过了每个节点的 CDM 数量,就会有一个或多个线程被迫共享一个 CDM。每个线程使用的 cdm 句柄存储在线程本地存储(TLS)中,在每次通信操作时都会引用该句柄。

shmemx_thread_quiet 例程用于等待特定线程关联的 CQ 中的所有事件完成。在资源过度分配的情况下,如果多个线程共享同一个 CQ, shmemx_thread_quiet 会等待所有共享该 CQ 的线程的所有事件完成。

以下是线程与 DMAPP 网络资源关系的 mermaid 流程图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef thread fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
    classDef cdm fill:#FFEBEB,stroke:#E68994,stroke-width:2px
    classDef cq fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px

    A(PE):::process --> B(线程 1):::thread
    A --> C(线程 2):::thread
    A --> D(线程 3):::thread
    B --> E(CDM 1):::cdm
    C --> F(CDM 2):::cdm
    E --> G(CQ 1):::cq
    F --> H(CQ 2):::cq
3.3 上下文实现细节

上下文 - 域实现中有两种不同的上下文原型设计:

  • 设计 1:基于域的资源共享 :每个域有自己的 CDM,该 CDM 中的所有上下文共享同一个 CQ。由于所有内存排序操作都是基于上下文的,因此 CQ 跟踪整个域的事件完成情况用处不大。每个上下文的事件完成情况通过一个唯一的 sync id 单独跟踪,该 sync id 在 SHMEM 库级别进行跟踪,而不是在 DMAPP 级别。 shmem ctx quiet 操作会等待特定上下文关联的所有 sync id 完成。

以下是基于域的资源共享设计的 mermaid 流程图:

graph LR
    classDef pe fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef domain fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
    classDef context fill:#FFEBEB,stroke:#E68994,stroke-width:2px
    classDef cdm fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef cq fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A(PE):::pe --> B(域 1):::domain
    A --> C(域 2):::domain
    B --> D(上下文 1):::context
    B --> E(上下文 2):::context
    C --> F(上下文 3):::context
    C --> G(上下文 4):::context
    B --> H(CDM 1):::cdm
    C --> I(CDM 2):::cdm
    H --> J(CQ 1):::cq
    I --> K(CQ 2):::cq
  • 设计 2:基于上下文的资源共享 :在这种设计中,每个上下文有自己的 CDM,所有内存排序操作通过映射到该 CDM 的 CQ 进行跟踪。域只是具有相似属性的 CDM 组。
4. 特性对比分析
4.1 实验设置

实验使用 Cray SHMEM 版本 7.4.0,在一个 52 节点的 Cray XC 系统上进行,每个节点配备 36 核 Intel Broadwell 处理器,采用 Cray 开发的 Aries 互连架构。使用 Cray 编程环境和 Cray 编译器环境(CCE)版本 8.4 进行测试,所有微基准测试采用 OpenMP 与 OpenSHMEM 的混合设计。

4.2 线程本地存储(TLS)的影响

在线程安全扩展设计中,每个注册的线程使用线程本地存储(TLS)来存储 cdm 句柄。为了分析使用 TLS 的性能影响,我们修改了 OSU 微基准测试,创建了线程级别为 SHMEM_THREAD_MULTIPLE 的多线程 PUT 基准测试。分析了一对 PE 中每个 PE 的 32 个注册线程进行不同数据大小通信调用时的节点间通信情况。

测试结果表明,在大数据量时,使用 TLS 存储 cdm 句柄和使用局部变量存储 cdm 句柄的性能没有差异。但在小数据量(小于 512 字节)时,使用局部变量存储 cdm 句柄的版本( cdm - handle - no - TLS )比使用 TLS 存储的版本( cdm - handle - use - TLS )性能高 8%。在 GCC 和 CCE 编译器上都观察到了类似的性能表现。

数据大小 cdm - handle - use - TLS 性能 cdm - handle - no - TLS 性能 性能差异
小于 512 字节 相对较低 相对较高 cdm - handle - no - TLS cdm - handle - use - TLS 高 8%
大于 512 字节 无明显差异 无明显差异
4.3 显式和隐式非阻塞操作的使用

在基于域的资源共享设计中,每个上下文事件的唯一 sync id 会被跟踪。只有显式非阻塞操作会生成 sync id ,隐式非阻塞操作不会。

通过修改 OSU 微基准测试,使用 2 个 PE(每个 PE 32 个线程)在不同节点上,采用 32 个域且每个域 1 个上下文的设计进行测试。每个域对象仅由一个线程访问,由于每个域只有一个上下文,因此可以直接在 CQ 上跟踪内存排序。

测试结果显示,对于小于 1M 的小消息大小,使用隐式操作的延迟比使用显式操作低 45%。在大数据量时,两种操作方式没有明显的性能差异。这是因为在 DMAPP 中,对于小数据量的隐式操作进行了优化,将事件链接在一起并为一组非阻塞事件生成一个唯一的 sync id ,而不是每个事件一个 sync id

在基于上下文的资源共享设计中,可以避免这种性能下降。基于域的资源共享需要将所有事件转换为显式操作来跟踪 sync id ,而基于上下文的资源共享则不需要。

综上所述,线程安全和上下文 - 域特性为 OpenSHMEM 应用提供了不同的多线程解决方案。通过对这些特性的详细分析和对比,我们可以根据具体的应用场景选择合适的方案,以提高应用程序的性能和可扩展性。

4.4 对不同线程级别的支持

OpenSHMEM 目前提出了两种线程级别: SHMEM_THREAD_SINGLE SHMEM_THREAD_MULTIPLE
- SHMEM_THREAD_SINGLE :在这种线程级别下,在整个应用程序的生命周期内,只有一个线程可以进行 OpenSHMEM 调用。这意味着在一个 PE 中,即使存在多个线程,也只有一个线程能够与 OpenSHMEM 库进行交互。
- SHMEM_THREAD_MULTIPLE :在该线程级别下,多个线程可以同时独立地进行 OpenSHMEM 调用。这允许在一个 PE 中的多个线程同时参与到共享内存的通信操作中,从而提高了并发性能。

在使用线程安全特性时, shmemx_init_thread 函数用于指定应用程序的线程级别。例如:

int required_threading_type = SHMEM_THREAD_MULTIPLE;
shmemx_init_thread(required_threading_type);
4.5 内存排序差异

线程安全和上下文 - 域特性在内存排序方面存在差异。
- 线程安全特性 :使用 shmemx_thread_fence shmemx_thread_quiet 进行内存排序。 shmemx_thread_fence 对特定线程的通信进行排序,确保该线程的通信操作按照一定的顺序执行。 shmemx_thread_quiet 等待特定线程的所有未完成操作完成。例如:

shmemx_thread_fence();
shmemx_thread_quiet();
  • 上下文 - 域特性 :使用 shmemx_ctx_fence shmemx_ctx_quiet 进行上下文级别的内存排序。这些操作只影响指定上下文的通信操作。例如:
shmemx_ctx_fence(ctx);
shmemx_ctx_quiet(ctx);
4.6 资源利用效率
  • 线程安全特性 :在多线程应用中,每个注册的线程会获得自己的 CDM 和 CQ。如果注册的线程数量超过了每个节点的 CDM 数量,会导致资源竞争,部分线程需要共享 CDM 和 CQ,从而影响性能。
  • 上下文 - 域特性
    • 基于域的资源共享设计 :多个上下文共享同一个 CQ,需要在 SHMEM 库级别跟踪 sync id ,对于小数据量的显式操作可能会导致性能下降。
    • 基于上下文的资源共享设计 :每个上下文有自己的 CDM 和 CQ,避免了基于域的资源共享设计中的性能问题,资源利用更加高效。
5. 性能分析
5.1 修改后的多线程 OSU 微基准测试

使用修改后的多线程 OSU 微基准测试对线程安全和上下文 - 域扩展进行性能分析。测试包括不同数据大小的通信操作,分析了线程本地存储(TLS)、显式和隐式非阻塞操作等因素对性能的影响。
- TLS 影响 :如前面所述,在小数据量时,不使用 TLS 存储 cdm 句柄的性能更好。
- 显式和隐式非阻塞操作 :在小消息大小下,隐式操作的性能优于显式操作。

5.2 全对全集体通信模式的性能分析

对使用线程安全和上下文 - 域实现的全对全集体通信模式进行性能分析。通过实验可以观察到不同特性在集体通信中的性能表现,根据具体的应用场景选择合适的特性可以提高集体通信的效率。

6. 总结与建议

线程安全和上下文 - 域特性为 OpenSHMEM 应用提供了增强的多线程支持,有助于提高应用程序的并发性能、减少通信开销和提升可扩展性。以下是一些总结和建议:
- 特性选择
- 如果应用程序的线程数量较少,且对资源竞争不太敏感,可以考虑使用线程安全特性。
- 如果需要更细粒度的通信控制和高效的资源利用,特别是在处理大量小数据量通信时,上下文 - 域特性的基于上下文的资源共享设计可能更合适。
- 性能优化
- 在小数据量通信时,避免使用 TLS 存储 cdm 句柄,尽量使用隐式非阻塞操作。
- 根据应用程序的线程级别和通信模式,合理配置资源,避免资源过度竞争。

通过深入理解和合理使用线程安全和上下文 - 域特性,开发者可以充分发挥 OpenSHMEM 的潜力,开发出高性能的 HPC 应用程序。未来,随着硬件和软件技术的不断发展,这些特性可能会进一步优化和扩展,为 HPC 领域带来更多的可能性。

AI智能图表创作平台,轻松对话绘图 Next AI Draw.io 是一款融合大语言模型 draw.io 的创新型图表绘制平台。无需掌握复杂的绘图规则,只需通过自然语言输入,即可完成图表构建、修改增强,帮助开发者和可视化创作者大幅提升效率。无论你是想绘制 AWS 架构图、GCP 拓扑,还是一个带有动画连接器的系统结构图,这款工具都能通过智能对话快速呈现。 核心亮点 LLM驱动的图表构建 通过 Chat 接口 AI 对话,快速生成符合语义的图表,轻松支持 draw.io XML 格式解析。 图像识别复制增强 上传一张已有图表或架构草图,AI 自动识别结构并重建图表,可进一步优化样式或内容。 图表版本管理 内置图表历史记录系统,支持版本切换回滚,便于团队协作修改回溯。 交互式绘图对话体验 内置对话界面,可边聊边画图,所见即所得,轻松优化图表结构排版。 多云架构模板一键生成 支持 AWS、GCP、Azure 架构图自动生成,适配图标库,适合开发、运维、架构师使用。 GCP架构图 动画连接器 支持为图表元素添加动态连接器,提升图表交互性演示感。 技术架构支持 Next.js:提供稳定高性能的前端体验 Vercel AI SDK:整合流式对话多模型支持 react-drawio:实现图表编辑可视化渲染 多模型接入:支持 OpenAI、Anthropic、Google、Azure、DeepSeek、Ollama 等主流 AI API claude-sonnet-4-5 专项训练:在 AWS 架构图任务上表现优异
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值