其它相关操作
MPI_DIMS_CREATE(nnodes, ndims,dims)
IN nnodes 网格中的结点数(整数)
IN ndims 笛卡尔维数(整数)
INOUT dims 大小为ndims的整数数组,定义每一维的结点数
int MPI_Dims_create(int nnodes, int ndims, int *dims)
MPI_DIMS_CREATE(NNODE, NDIMS, DIMS, IERROR)
INTEGER NNODES, NDIMS, DIMS(*), IERROR

MPI_DIMS_CREATE根据用户指定的总维数ndims和总的进程数nnodes,帮助用户在每一维上选择进程的个数。返回结果放在dims中,它可以作为MPI_CART_CREATE的输入参数。但是用户也可以根据需要指定特定某一维i的进程数,比如置dims[i]=k>0,则本调用不会修改dims[i]的值,只有对于dims[i]=0的维,本调用才根据合适的划分算法给它重新赋值。本调用不允许dims[i]的初始值为负。


MPI_CART_GET(comm, maxdims, dims, periods, coords)
IN comm 带有笛卡尔结构的通信域(句柄)
IN maxdims 最大维数(整数)
OUT dims 返回各维的进程数(整数数组)
OUT periods 返回各维的周期特性(逻辑数组)
OUT coords 调用进程的笛卡尔坐标(整数数组)
int MPI_Cart_get(MPI_Comm comm, int maxdims, int *dims, int *periods, int *coords)
MPI_CART_GET(COMM, MAXDIMS, DIMS, PERIODS, COORDS, IERROR)
INTEGER COMM, MAXDIMS, DIMS(*), COORDS(*), IERROR
LOGICAL PERIODS(*)

MPI_CART_GET返回给定通信域的拓扑信息,包括每一维的进程数dims,每一维的周期性periods和当前调用进程的笛卡儿坐标coords。

MPI_CART_RANK(comm, coords, rank)
IN comm 带有笛卡尔结构的通信域(句柄)
IN coords 卡氏坐标(整数数组)
OUT rank 卡氏坐标对应的一维线性坐标(整数)
int MPI_Cart_rank(MPI_Comm comm, int *coords, int *rank)
MPI_CART_RANK(COMM, COORDS, RANK, IERROR)
INTEGER COMM, COORDS(*), RANK, IERROR

MPI_CART_RANK将给定拓扑的笛卡尔坐标转换成同一进程的用MPI_COMM_RANK调用得到的顺序编号。

MPI_CARTDIM_GET(comm, ndims)
IN comm 带有笛卡尔结构的通信域(句柄)
OUT ndims 笛卡尔网格的维数(整数)
int MPI_Cartdim_get(MPI_Comm comm, int *ndims)
MPI_CARTDIM_GET(COMM, NDIMS, IERROR)
INTEGER COMM, NDIMS, IERROR

MPI_CARTDIM_GET返回comm对应的笛卡尔结构的维数ndims。

MPI_CART_COORDS(comm, rank, maxdims, coords)
IN comm 带有笛卡尔结构的通信域(句柄)
IN rank 一维线性坐标(整数)
IN maxdims 最大维数(整数)
OUT coords 返回该一维线性坐标对应的卡氏坐标
int MPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int *coords)
MPI_CART_COORDS(COMM, RANK, MAXDIMS, COORDS, IERROR)
INTEGER COMM, RANK, MAXDIMS, COORDS(*), IERROR

MPI_CART_COORDS将进程rank的顺序编号转换为笛卡儿坐标coords,其中maxdims是维数。

下面的例子通过定义虚拟拓扑,实现数据的接力传送。

#include <stdio.h>
#include "mpi.h"

int main( argc, argv )
int argc;
char **argv;
{
int rank, value, size, false=0;
int right_nbr, left_nbr;
MPI_Comm ring_comm;
MPI_Status status;

MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &size );
MPI_Cart_create( MPI_COMM_WORLD, 1, &size, &false, 1, &ring_comm );/*创建一维网格,false意味着没有周期性(两端外的进程标识为MPI_PROC_NULL),1表示可以重排序,得到的拓扑坐标相邻关系为:

MPI_PROC_NULL, 0, 1, ... , size-1 , MPI_PROC_NULL

*/
MPI_Cart_shift( ring_comm, 0, 1, &left_nbr, &right_nbr );/*通过在定义的网格上的平移得到左右侧进程的标识*/
MPI_Comm_rank( ring_comm, &rank );/*得到在新拓扑中的标识或坐标*/
MPI_Comm_size( ring_comm, &size );/*得到新通信域中进程的个数*/
do {
if (rank == 0) {/*进程0负责读入数据并向下一个进程传递数据*/
scanf( "%d", &value );
MPI_Send( &value, 1, MPI_INT, right_nbr, 0, ring_comm );/*将数据传送到右面的进程*/
}
else {
MPI_Recv( &value, 1, MPI_INT, left_nbr, 0, ring_comm,
&status );/*后面的进程从左边的进程接收数据*/
MPI_Send( &value, 1, MPI_INT, right_nbr, 0, ring_comm );/*将接收到的数据在传递给右面的进程*/
}
printf( "Process %d got %d\n", rank, value );/*各进程打印各自得到的数据*/
} while (value >= 0);/*若读入的数据非负,则继续读入并传递*/

MPI_Finalize( );
}