【问题标题】:MPI - Sending segments of an arrayMPI - 发送数组的段
【发布时间】:2013-03-07 04:12:24
【问题描述】:

所以我有一个双打数组。我想发送,比如每 5 次双倍发送到接收过程。所以本质上,我需要一种发送特定双打的方法,它们之间有跨步。除了将双打存储到发送缓冲区之外,是否有执行此操作的功能?制作自己的派生类型会更好吗?

【问题讨论】:

    标签: arrays mpi send stride


    【解决方案1】:

    您绝对应该创建一个 MPI 数据类型;它使 MPI 库有机会避免从数组中编组的额外副本,并且在这种情况下使用 MPI_Type_vector() 非常简单:

    #include <stdio.h>
    #include <stdlib.h>
    #include <mpi.h>
    
    int main(int argc, char** argv)
    {
        int size, rank;
        const int bigsize=50;
        const int stride = 5;
        const int count = (bigsize + stride - 1)/stride;
    
        const int sender = 0;
        const int receiver = 1;
        const int mytag = 1;
    
        MPI_Init(&argc,&argv);
        MPI_Comm_size(MPI_COMM_WORLD,&size);
        MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    
        if (size < 2) {
            fprintf(stderr,"%s: Require at least two processors.\n", argv[0]);
            MPI_Finalize();
            exit(-1);
        }
    
    
        if(rank == sender)
        {
            double bigarray[bigsize];
            for (int i=0; i<bigsize; i++)
                bigarray[i] = 0.;
    
            for (int i=0; i<bigsize; i+=stride)
                bigarray[i] = i/stride;
    
            printf("[%d]: ", rank);
            for (int i=0; i<bigsize; i++)
                printf("%lf ", bigarray[i]);
            printf("\n");
    
            MPI_Datatype everyfifth;
    
            MPI_Type_vector( count, 1, stride, MPI_DOUBLE, &everyfifth);
            MPI_Type_commit(&everyfifth);
    
            MPI_Send(bigarray, 1, everyfifth, receiver, mytag, MPI_COMM_WORLD);
    
            MPI_Type_free(&everyfifth);
        }
        else if( rank == receiver )
        {
            double littlearray[count];
    
            MPI_Status status;
    
            MPI_Recv(littlearray, count, MPI_DOUBLE, sender, mytag,
                        MPI_COMM_WORLD, &status);
    
            printf("[%d]: ", rank);
            for (int i=0; i<count; i++)
                printf("%lf ", littlearray[i]);
            printf("\n");
        }
    
        MPI_Finalize();
    
        return 0;
    }
    

    编译运行给出

    $ mpicc -o vector vector.c -std=c99
    $ mpirun -np 2 ./vector
    [0]: 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 2.000000 0.000000 0.000000 0.000000 0.000000 3.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 0.000000 0.000000 5.000000 0.000000 0.000000 0.000000 0.000000 6.000000 0.000000 0.000000 0.000000 0.000000 7.000000 0.000000 0.000000 0.000000 0.000000 8.000000 0.000000 0.000000 0.000000 0.000000 9.000000 0.000000 0.000000 0.000000 0.000000 
    [1]: 0.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 
    

    【讨论】:

    • 一个问题 - 我这样做了,但是它比发送整个数组要慢。你愿意解释一下为什么吗?还有一种更有效的方法,因为我在循环中使用了数千次迭代。
    • 视情况而定。如果无论哪种方式数据都很小——因此消息的长度不会显着影响通信时间——那么仅选择相关位的额外开销可能会很明显;这将取决于网络层。还有实际创建、提交和释放类型的开销,但只需执行一次,而不是每条消息一次,因此您可以在多次迭代中分摊。
    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 2015-06-06
    • 1970-01-01
    • 2019-08-12
    • 2013-11-13
    • 2021-06-11
    • 2013-02-11
    • 2018-11-11
    相关资源
    最近更新 更多