消息传递接口/MPI 函数参考
此页面列出了MPI中使用的函数的简要说明。
int MPI_Send( void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm )
这将buf
的内容发送到等级为dest
的目标,而接收端调用MPI_Recv
。
int MPI_Recv( void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status )
这将buf
填充来自等级为source
的源的数据,而发送方调用MPI_Send
。
int MPI_Bcast ( void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm )
这将buffer
的内容在root
上发送到所有其他进程。因此,之后buffer
的前count
个元素在所有节点上都是相同的。 [1]
int MPI_Open_port(MPI_Info info, char *port_name)
这将创建一个端口,其他进程可以连接到该端口。作为port_name
字符串传递的缓冲区必须至少MPI_MAX_PORT_NAME
长,并将包含其他进程需要知道的唯一标识符以进行连接。
int MPI_Comm_accept(char *port_name, MPI_Info info, int root, MPI_Comm comm, MPI_Comm *newcomm)
在调用MPI_Open_port()
之后,此函数将等待连接。
int MPI_Comm_connect(char *port_name, MPI_Info info, int root, MPI_Comm comm, MPI_Comm *newcomm)
这将打开一个连接到另一个进程,该进程正在等待MPI_Comm_accept()
。port_name
参数必须与另一个进程的port_name
相同,该port_name
是从MPI_Open_port
返回的。
以下函数通过应用简单的函数(如求和)将跨处理器的数组数据规约到一个或多个处理器上的标量。
int MPI_Scan ( void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm )
参见 [4].
int MPI_Allreduce ( void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm )
这在所有节点上对每个节点的sendbuf
执行由MPI_Op
指定的运算。例如,如果节点 0 在其sendbuf
中分别具有{0, 1, 2}
,而节点 1 具有{3, 4, 5}
,并且如果两者都调用MPI_Allreduce(sendbuf, foo, 3, MPI_INT, MPI_SUM, world)
,则两个节点上由foo
指向的缓冲区的内容将为
- {0+3, 1+4, 2+5} = {3, 5, 7}
对于P个进程的性能:。 [5]
int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm);
MPI_Comm_split()
在每个进程中创建一个新的通信器。生成的通信器对于提供了相同color
参数的进程是通用的。进程可以通过提供MPI_UNDEFINED
作为color
来选择不获取通信器,这将为该进程生成MPI_COMM_NULL
。
例如,以下代码将MPI_COMM_WORLD
拆分为三个通信器,分别“颜色”为 0、1 和 2。
#include<iostream> #include<mpi.h> using namespace std; int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm comm; MPI_Comm_split(MPI_COMM_WORLD, rank % 3, -rank*2, &comm); // The keys need not be positive or contiguous. int rank2; MPI_Comm_rank(comm, &rank2); cout << "My rank was " << rank << " now " << rank2 << " color: " << rank % 3 << "\n"; MPI_Finalize(); }
使用八个进程运行,这将输出以下内容(以不确定的顺序)
My rank was 0 now 2 color: 0 My rank was 8 now 2 color: 1 My rank was 8 now 1 color: 2 My rank was 3 now 1 color: 0 My rank was 4 now 1 color: 1 My rank was 5 now 0 color: 2 My rank was 6 now 0 color: 0 My rank was 7 now 0 color: 1 My rank was 8 now 0 color: 1
以下函数协同工作以允许进程之间的非阻塞异步通信。 [6] 一个进程发送,而另一个进程接收。发送方必须在删除缓冲区之前检查操作是否已完成。MPI_Wait()
是一个阻塞等待,而MPI_Test
是非阻塞的。
MPI_Isend()
和MPI_Irecv()
调用不需要按顺序进行。也就是说,进程 42 可以调用MPI_Irecv()
三次以开始接收来自进程 37、38 和 39 的数据,这些进程可以随时发送。
int MPI_Isend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request);
---
int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request recvtag, MPI_Comm comm, MPI_Status *status);
int MPI_Wait(MPI_Request *request, MPI_Status *status);
int MPI_Test(MPI_Request *request, int* flag, MPI_Status* status);
示例代码
#include<iostream> #include<mpi.h> using namespace std; int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm comm; int sources[] = {3,4,5}; int dest = 1; int tag =42; if (rank == sources[0] || rank == sources[1] || rank == sources[2]) { double x[] = { 1*rank, 2*rank, 3*rank}; MPI_Request r; MPI_Isend(x, 3, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD, &r); cout << "Process " << rank << " waiting...\n"; MPI_Status status; MPI_Wait(&r, &status); cout << "Process " << rank << " sent\n"; } else if(rank == dest) { double x[3][3]; MPI_Request r[3]; for (int i = 0; i !=3; ++i) { MPI_Irecv(x[i], 3, MPI_DOUBLE, sources[i], tag, MPI_COMM_WORLD, &r[i]); cout << "Process " << rank << " waiting for " << sources[i] << " on recv.\ \n"; } for (int i = 0; i !=3; ++i) { MPI_Status status; MPI_Wait(&r[i], &status); cout << "Process " << rank << " got " << x[i][0] << " " << x[i][1] << " " <\ < x[i][2] << ".\n"; } } MPI_Finalize(); }
读者请求扩展此页面以包含更多材料。 您可以通过添加新材料(了解如何)或在阅览室中寻求帮助来提供帮助。 |
int MPI_Init(int *argc, char ***argv); int MPI_Finalize(void); int MPI_Comm_rank(MPI_Comm comm, int *rank); int MPI_Comm_size(MPI_Comm comm, int *size); int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count); int MPI_Type_extent(MPI_Datatype datatype, MPI_Aint *extent); int MPI_Type_struct(int count, int *array_of_blocklengths, MPI_Aint *array_of_displacements, MPI_Datatype *array_of_types, MPI_Datatype *newtype); int MPI_Scatter(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvcount, int root, MPI_Comm comm); Performance potential: As good as log_2 (N) as bad as N. http://www.pdc.kth.se/training/Talks/MPI/Collective.I/less.html#perf_scatter_image int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm); -- [7]
- 请求);
int MPI_Sendrecv(void* sendbuf, int sendcount, MPI_Datatype datatype, int dest, int sendtag, void* recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status); int MPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype, int dest, int sendtag, int source, int int MPI_Request_free(MPI_Request *request); int MPI_Group_rank(MPI_Group group, int *rank); int MPI_Group_size(MPI_Group group, int *size); int MPI_Comm_group(MPI_Comm comm, MPI_Group *group); int MPI_Group_free(MPI_Group *group); int MPI_Group_incl(MPI_Group *group, int n, int *ranks, MPI_Group *newgroup); int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newgroup); int MPI_Wtime(void); int MPI_Get_processor_name(char *name, int *resultlen);
- 对 MPI 语义的出色解释
- “集体通信”由戴夫·埃尼斯博士撰写
此页面或部分是一个未开发的草稿或提纲。 您可以帮助开发工作,或者您可以在项目室中寻求帮助。 |