并行计算(三)——衍生数据类型

在MPI中,除了有与C语言类似的MPI_INT, MPI_DOUBLE等内建类型外,还提供了用户自定义的衍生类型(Derived Datatype)。

MPI_Type_vector

最简单也是最常用的衍生数据类型就是这个向量类型,声明方法为:

MPI_Type_vector(count, blocklen, stride, oldtype, newtype);
参数 count表示数据块的重复次数, blocklen表示单一数据块的数据长度, stride表示数据块重复一次的总长度,如下图所示
stride=5
XXX  XXX  XXX  XXX
blocklen=3
count=4
oldtype表示的是存放原始数据的数组中元素的类型,一般为 MPI_INTMPI_DOUBLE等内建类型,当然也可也是衍生类型。而 newtype则就是一个 MPI_Datatype类型的变量,用来表示新生成的数据类型。为了使数据类型生成,还需要在声明后进行执行:
MPI_Type_commit(newtype);
下面的例子中,0号处理器使用一维数组存放一个矩阵, 将它最右边的一列传递给1号处理器并存放在一个空矩阵的最左一列。然后0号处理器再将右下角的四分之一矩阵传递给2号处理器,并存放在左下角。
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int rank, size,nx,ny,row,col,count,blocklen,stride;
    double *A;
    MPI_Status status;
    MPI_Datatype newtype;
    MPI_Datatype quarterType;

    MPI_Init(&argc, &argv);               /* Initialize MPI               */
    MPI_Comm_size(MPI_COMM_WORLD, &size); /* Get the number of processors */
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* Get my number                */

    nx=8; ny=16;
    A=(double *)calloc(nx*ny,sizeof(double));
    if (rank==0){
        printf("Matrix A on proc 0\n");
        for (row=0; row<nx;row++){
            for (col=0; col<ny;col++){
        A[row*ny+col]=(double)col+100*row+1000;
            printf("%d ", (int)A[row*ny+col]);
            }
            printf("\n");
        }
        printf("\n");
    }
    /* left colummn to right column*/
    count=nx; blocklen=1; stride=ny;
    MPI_Type_vector(count,blocklen,stride,MPI_DOUBLE,&newtype);
    MPI_Type_commit(&newtype);

    /* right bottom quarter to left bottom quarter*/
    blocklen = ny/2;
    stride = ny;
    count = nx /2;
    MPI_Type_vector(count,blocklen,stride,MPI_DOUBLE,&quarterType);
    MPI_Type_commit(&quarterType);

    /* Send last column, notice the message length = 1 ! */
    if (rank == 0) {
        MPI_Send(&A[ny-1], 1, newtype, 1, 111, MPI_COMM_WORLD);
        MPI_Send(&A[ny * nx / 2 + ny / 2], 1, quarterType, 2, 222, MPI_COMM_WORLD);

    }
    else if (rank==1) {
        MPI_Recv(&A[0], 1, newtype, 0, 111, MPI_COMM_WORLD, &status);
        printf("Matrix A on proc 1\n");
        for (row=0; row<nx; row++)
        {
            for (col=0; col<ny; col++)
                printf("%4d ", (int)A[row*ny+col]);
            printf("\n");
        }
    }
    else if (rank == 2) {
        MPI_Recv(&A[ny * nx / 2], 1, quarterType, 0, 222, MPI_COMM_WORLD, &status);
        printf("Matrix A on proc 2\n");
        for (row=0; row<nx; row++)
        {
            for (col=0; col<ny; col++)
                printf("%4d ", (int)A[row*ny+col]);
            printf("\n");
        }
    }

    free(A);
    MPI_Type_free(&newtype);
    MPI_Finalize();

    return 0;
}

注意,在使用衍生类型的时候,由于类型已经包含了所有需要的元素,因此,发送或者接收时 count的值应该为1或者是相应的值,而不是原来数组的长度。

MPI_Type_indexed

这个衍生类型比前一种向量类型更加自由的一种数组类型,它的调用方法为:
MPI_Type_indexed(count, lenarr, indexarr, oldtype, newtype);
参数的具体意义如下图所示,其中 indexarr表示的是每个元素的起始位置在原始数据中的index, lenarr则是指每个数据块的长度。
 indexarr[0]=2 indexarr[1]=8 indexarr[2]=15
   
  XXX   XXXXX  XXX
 lenarr[0]=3 lenarr[1]=5 lenarr[2]=3

MPI_Type_struct

这种数据类型比前面两种更加自由,它不仅可以包含不同长度的数据块作为数组元素,还可以包含不同数据类型的数据块,调用方法为:

MPI_Type_struct(count, lenarr, indexarr, typearr, newtype);
其中, typearr就表示了对应元素的数据类型。
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值