常用 MPI 函数和结构体说明备忘 MPI_Comm_split_type

1,特别说明

函数原型

#include <mpi.h>

int MPI_Comm_split_type(MPI_Comm comm, int split_type, int key,

    MPI_Info info, MPI_Comm *newcomm);

参数说明

comm:     类型: MPI_Comm

含义: 输入参数,表示要进行分割的通信器句柄。这个通信器包含了一组进程,这些进程将根据指定的分割类型被分成多个子组。

split_type:    类型: int

含义: 输入参数,指定要分组的进程类型。这个整数值决定了如何将进程分成不同的子组。可以使用预定义的常量(如 MPI_COMM_TYPE_SHARED)来指定分割类型。

key:    类型: int

含义: 输入参数,控制新通信器中进程的排名分配。每个进程可以提供一个整数值,MPI 将根据这个值对进程进行排序。如果多个进程的 key 值相同,则根据它们在原始通信器中的排名来打破平局。

 info:      类型: MPI_Info

含义: 输入参数,提供附加信息的句柄。这个参数可以用于传递与分割相关的特定信息,通常在某些实现中可能会被使用,但在标准 MPI 中并不是必需的。

newcomm:    类型: MPI_Comm*

含义: 输出参数,返回新创建的通信器句柄。每个子组的进程将共享这个新的通信器,允许它们在各自的子组内进行通信。

函数描述

MPI_Comm_split_type 函数根据指定的 split_type 将与 comm 相关联的进程组分割成不重叠的子组。每个子组包含所有相同类型的进程。在每个子组内,进程的排名按照 key 参数的值进行排序,平局通过原始组中的排名来打破。为每个子组创建一个新的通信器,并将其返回在 newcomm 中。

这个函数是一个集体调用;所有进程必须提供相同的 split_type,但每个进程可以提供不同的 key 值。一个例外是,进程可以提供 MPI_UNDEFINED 作为类型值,在这种情况下,newcomm 返回 MPI_COMM_NULL。

分割类型示例

  • MPI_COMM_TYPE_SHARED: 将通信器分割为可以创建共享内存区域的子通信器。
  • OMPI_COMM_TYPE_NODE: 与 MPI_COMM_TYPE_SHARED 同义。
  • OMPI_COMM_TYPE_HWTHREAD: 将通信器分割为属于同一硬件线程的子通信器。
  • OMPI_COMM_TYPE_CORE: 将通信器分割为属于同一核心/处理单元的子通信器。
  • OMPI_COMM_TYPE_L1CACHE: 将通信器分割为属于同一 L1 缓存的子通信器。
  • OMPI_COMM_TYPE_L2CACHE: 将通信器分割为属于同一 L2 缓存的子通信器。
  • OMPI_COMM_TYPE_L3CACHE: 将通信器分割为属于同一 L3 缓存的子通信器。
  • OMPI_COMM_TYPE_SOCKET: 将通信器分割为属于同一插槽的子通信器。
  • OMPI_COMM_TYPE_NUMA: 将通信器分割为属于同一 NUMA 节点的子通信器。
  • OMPI_COMM_TYPE_BOARD: 将通信器分割为属于同一板的子通信器。
  • OMPI_COMM_TYPE_HOST: 将通信器分割为属于同一主机的子通信器。
  • OMPI_COMM_TYPE_CU: 将通信器分割为属于同一计算单元的子通信器。
  • OMPI_COMM_TYPE_CLUSTER: 将通信器分割为属于同一集群的子通信器。

注意事项

  • 以 OMPI_ 前缀表示的通信器类型是特定于 Open MPI 的,并不是 MPI 标准的一部分。使用时应保护 OPEN_MPI C 预处理器宏。

错误处理

几乎所有 MPI 例程都会返回一个错误值;C 例程返回函数的值,Fortran 例程在最后一个参数中返回。错误处理程序可以通过 MPI_Comm_set_errhandler 更改,预定义的错误处理程序 MPI_ERRORS_RETURN 可用于返回错误值。注意,MPI 不保证在错误发生后 MPI 程序可以继续执行。

2,NUMA 与 MPI_COMM_TYPE_SHARED 的相互作用

在 NUMA(非统一内存访问)系统中,不同节点上的进程之间的共享内存和 MPI 通信的行为如下:

2.1. 不同节点上的进程之间的共享内存

在 NUMA 系统中,通常情况下,不同节点上的进程不能直接共享内存。每个节点有自己的本地内存,进程只能直接访问其所在节点的内存。虽然可以通过一些机制(如使用操作系统提供的共享内存功能)在不同节点之间实现共享内存,但这通常涉及到额外的开销和复杂性。

  • 共享内存:在 NUMA 系统中,进程可以使用 POSIX 共享内存(如 shm_open 和 mmap)或 System V 共享内存(如 shmget 和 shmat)来创建跨节点的共享内存区域。然而,这种共享内存的访问速度可能会受到影响,因为跨节点访问会导致更高的延迟。

2.2. MPI_COMM_TYPE_SHARED 和通信域

关于 MPI_COMM_TYPE_SHARED,它是 MPI 中用于表示共享内存通信的一个通信器类型。根据 MPI 的定义,MPI_COMM_TYPE_SHARED 通常用于将同一节点上的进程分组在一起,以便它们可以利用共享内存进行高效通信。

  • MPI_COMM_TYPE_SHARED:这个类型的通信器用于将进程分组在同一节点上,允许它们使用共享内存进行通信。它并不适用于跨节点的进程。换句话说,只有在同一节点上的进程才能进入 MPI_COMM_TYPE_SHARED 通信域。

2.3. 结论

  • 不同节点上的进程之间不能直接共享内存,虽然可以通过操作系统的共享内存机制实现,但这通常不是高效的。
  • 不同节点上的进程不能按照 MPI_COMM_TYPE_SHARED 规则进入同一个通信域,因为 MPI_COMM_TYPE_SHARED 仅适用于同一节点上的进程。

如果需要在不同节点之间进行通信,通常会使用 MPI 的其他通信机制(如点对点通信、广播、归约等),而不是依赖于共享内存。

3,MPI 关键字常规说明

常用 MPI(消息传递接口)关键字的详细解释,常用 函数、类型和宏的含义:
MPI 函数和宏


MPI_Comm comm:
MPI_Comm 是一个通信器类型,用于定义一组进程之间的通信上下文。comm 是一个通信器的实例,通常用于指定进程间的通信范围。


MPI_Comm_rank:
函数原型:int MPI_Comm_rank(MPI_Comm comm, int *rank);
获取指定通信器中调用进程的排名(ID)。rank 是输出参数,返回当前进程在通信器中的唯一标识符。


MPI_Comm_size:
函数原型:int MPI_Comm_size(MPI_Comm comm, int *size);
获取指定通信器中进程的总数。size 是输出参数,返回通信器中进程的数量。


MPI_Get_processor_name:
函数原型:int MPI_Get_processor_name(char *name, int *resultlen);
获取当前进程所在的处理器的名称。name 是输出参数,resultlen 是返回的名称长度。


MPI_Barrier:
函数原型:int MPI_Barrier(MPI_Comm comm);
在指定的通信器中执行屏障同步,确保所有进程在此点上同步,直到所有进程都到达屏障。


 MPI_Finalize:
函数原型:int MPI_Finalize();
结束 MPI 环境,释放所有 MPI 资源。所有 MPI 调用必须在此之前完成。


MPI_Comm_split_type:
函数原型:int MPI_Comm_split_type(MPI_Comm comm, int split_type, int key, MPI_Info info, MPI_Comm *newcomm);
根据指定的类型将通信器分割成多个子通信器。split_type 指定分割的类型,key 用于排序,info 是附加信息。


MPI_Comm_free:
函数原型:int MPI_Comm_free(MPI_Comm *comm);
释放指定的通信器,允许其占用的资源被回收。


MPI_Init:
函数原型:int MPI_Init(int *argc, char ***argv);
初始化 MPI 环境,必须在调用任何其他 MPI 函数之前调用。


MPI_Op_create:
函数原型:int MPI_Op_create(MPI_User_function *user_fn, int commute, MPI_Op *op);
创建一个用户自定义的操作,用于在 MPI 操作中使用。


MPI_Abort:
函数原型:int MPI_Abort(MPI_Comm comm, int errorcode);
终止 MPI 程序并返回错误代码。所有进程将被强制终止。


MPI_Wtime:
函数原型:double MPI_Wtime();
返回一个高精度的时间戳,通常用于测量时间间隔。


MPI_Status:
结构体类型,用于描述消息的状态,包括源进程、标签和错误代码等信息。


MPI_Sendrecv:
函数原型:int MPI_Sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status);
同时发送和接收消息,sendbuf 和 recvbuf 分别是发送和接收缓冲区。


15. MPI_Request:
结构体类型,用于表示非阻塞操作的请求句柄。


16. MPI_REQUEST_NULL:
宏,表示一个空的请求句柄,通常用于初始化或检查请求状态。


MPI_Irecv:
函数原型:int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request);
非阻塞接收消息,返回一个请求句柄以便后续检查。


MPI_Isend:
函数原型:int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request);
非阻塞发送消息,返回一个请求句柄以便后续检查。


MPI_Waitany:
函数原型:int MPI_Waitany(int count, MPI_Request array_of_requests[], int *index, MPI_Status *status);
等待任意一个请求完成,并返回完成的请求的索引。


MPI_STATUSES_IGNORE:
宏,表示在某些 MPI 调用中忽略状态信息。


MPI_Bcast:
函数原型:int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm);
广播消息,从根进程向所有其他进程发送数据。


MPI_Send:
函数原型:int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm);
发送消息到指定的目标进程。


MPI_Recv:
函数原型:int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status);
接收来自指定源进程的消息。


MPI_Wait:
函数原型:int MPI_Wait(MPI_Request *request, MPI_Status *status);
阻塞等待请求完成,并返回状态信息。


MPI_Allreduce:
函数原型:int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
在所有进程上执行归约操作,并将结果广播到所有进程。


MPI_IN_PLACE:
宏,表示在某些 MPI 调用中使用原地操作,通常用于减少内存使用。


MPI_Allgatherv:
函数原型:int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int *recvcounts, const int *displs, MPI_Datatype recvtype, MPI_Comm comm);
在所有进程上收集数据,并根据接收计数和偏移量将数据分发到接收缓冲区。


MPI_Datatype:
数据类型,用于定义发送和接收数据的格式。


MPI_Type_size:
函数原型:int MPI_Type_size(MPI_Datatype datatype, int *size);
获取指定数据类型的大小(以字节为单位)。


MPI_Scatterv:
函数原型:int MPI_Scatterv(const void *sendbuf, const int *sendcounts, const int *displs, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm);
将数据从根进程分散到所有进程,允许每个进程接收不同数量的数据。


MPI_Waitall:
函数原型:int MPI_Waitall(int count, MPI_Request array_of_requests[], MPI_Status array_of_statuses[]);
阻塞等待所有请求完成,并返回每个请求的状态信息。


MPI_Type_contiguous:
函数原型:int MPI_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype *newtype);
创建一个新的数据类型,表示多个连续的旧数据类型的组合。


MPI_Type_commit:
函数原型:int MPI_Type_commit(MPI_Datatype *datatype);
提交自定义数据类型,使其可用于发送和接收。


MPI_Type_free:
函数原型:int MPI_Type_free(MPI_Datatype *datatype);
释放自定义数据类型的资源。


MPI_Comm_split:
函数原型:int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm);
根据颜色和键将通信器分割成多个子通信器。


MPI_Op:
操作类型,用于定义在归约操作中使用的操作。


MPI_SUM:
常量,表示在归约操作中执行求和。


38. MPI_MAX:
常量,表示在归约操作中执行最大值计算。


MPI_MIN:
常量,表示在归约操作中执行最小值计算。


这些函数和宏是 MPI 的核心组成部分,提供了进程间通信、同步和数据管理的基本功能。。

4,特别说明

int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm)


输入参数:
comm: 通信器(句柄)
color: 控制子集分配的非负整数
key: 控制排名分配的整数

输出参数:
newcomm: 新创建的通信器(句柄)
IERROR: 仅Fortran使用,错误状态(整数)

4.1 描述


该函数将与 comm 关联的进程组划分为不相交的子组,每个颜色值对应一个子组。每个子组包含所有具有相同颜色值的进程。在每个子组内,进程按 key 参数的值排序,如果 key 值相同则按原组中的排名排序。为每个子组创建一个新的通信器并通过 newcomm 返回。进程可以提供 MPI_UNDEFINED 作为颜色值,此时 newcomm 将返回 MPI_COMM_NULL。这是一个集体调用,但每个进程可以提供不同的 color 和 key 值。

4.2 主要作用


1. 将一个通信组划分为多个不重叠的子组
可用于定义计算层次结构,如多重网格或线性代数计算
通过多次调用可创建重叠的通信结构
允许灵活地重新排序进程

4.3 注意事项


1. color 值必须为非负整数或 MPI_UNDEFINED
2. key 值用于控制子组内的排序,可以不唯一
3. 设置所有进程的 key 为 0 可保持原有的相对顺序

这是一个非常强大的机制,可以灵活地对进程组进行划分和重组,以适应不同的并行计算需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值