如何使用MPI分散和数组收集

时间:2016-10-17 07:07:52

标签: c parallel-processing mpi

我是MPI的新手,并使用C语言编写了以下程序。而不是使用指针,我想设置我的数组如下图所示。我的第一个数组元素读取正确,之后,它不会读取数组元素。如果这不是使用分散和聚集的正确方法,请告诉我 以下是我得到的结果:
:$ mpicc test.c -o test
:$ mpirun -np 4 test
1. Processor 0 has data: 0 1 2 3
2. Processor 0 has data 0
3. Processor 0 doubling the data, now has 5
2. Processor 1 has data 32767
3. Processor 1 doubling the data, now has 5
2. Processor 2 has data -437713961
3. Processor 2 doubling the data, now has 5
2. Processor 3 has data 60
3. Processor 3 doubling the data, now has 5
4. Processor 0 has data: 5 1 2 3

正确的结果应该是:
:$ mpicc test.c -o test
:$ mpirun -np 4 test
1. Processor 0 has data: 0 1 2 3
2. Processor 0 has data 0
3. Processor 0 doubling the data, now has 5
2. Processor 1 has data 1
3. Processor 1 doubling the data, now has 5
2. Processor 2 has data 2
3. Processor 2 doubling the data, now has 5
2. Processor 3 has data 3
3. Processor 3 doubling the data, now has 5
4. Processor 0 has data: 5 5 5 5

非常感谢任何帮助。以下代码使用4个处理器运行:

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

int main(int argc, char **argv) {
    int size, rank;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int globaldata[4];/*wants to declare array this way*/
    int localdata[4];/*without using pointers*/

    int i;
    if (rank == 0) {

        for (i=0; i<size; i++)
            globaldata[i] = i;

        printf("1. Processor %d has data: ", rank);
        for (i=0; i<size; i++)
            printf("%d ", globaldata[i]);
        printf("\n");
    }

    MPI_Scatter(globaldata, 1, MPI_INT, &localdata, 1, MPI_INT, 0, MPI_COMM_WORLD);

    printf("2. Processor %d has data %d\n", rank, localdata[rank]);
    localdata[rank]= 5;
    printf("3. Processor %d now has %d\n", rank, localdata[rank]);

    MPI_Gather(&localdata, 1, MPI_INT, globaldata, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if (rank == 0) {
        printf("4. Processor %d has data: ", rank);
        for (i=0; i<size; i++)
            printf("%d ", globaldata[i]);
        printf("\n");
    }


    MPI_Finalize();
    return 0;
}

1 个答案:

答案 0 :(得分:2)

您的设置和分散原则上是正常的。你的问题出在打印上,因为你误解了散点/聚集的细节。

当散布4元素数组时,每个进程只获得一个元素(正如您使用MPI_Scatter call()的第2和第5个参数定义的那样)。此元素存储在本地数组的0索引中。它实际上是一个标量。

通常,您可能会分散非常大的数组,并且每个进程可能仍然需要处理大型本地数组。在这些情况下,必须正确计算全局指数本地指数

假设存在以下玩具问题:您希望将数组[1 2 3 4 5 6]分散到两个进程。 Proc0应具有[1 2 3]部分,Proc1应具有[4 5 6]部分。在这种情况下,全局数组的大小为6,本地数组的大小为3. Proc0获取全局元素0,1,2并将它们分配给它的本地0,1,2.Proc1获取全局元素3,4 ,5并将它们分配给它的本地0,1,2。

当您了解MPI_Scatterv并不为每个过程假设相同数量的本地元素时,您可能会更好地理解这个概念。

此版本的代码似乎有效:

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

int main(int argc, char **argv) {
    int size, rank;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int globaldata[4];/*wants to declare array this way*/
    int localdata;/*without using pointers*/

    int i;
    if (rank == 0) {

        for (i=0; i<size; i++)
            globaldata[i] = i;

        printf("1. Processor %d has data: ", rank);
        for (i=0; i<size; i++)
            printf("%d ", globaldata[i]);
        printf("\n");
    }

    MPI_Scatter(globaldata, 1, MPI_INT, &localdata, 1, MPI_INT, 0, MPI_COMM_WORLD);

    printf("2. Processor %d has data %d\n", rank, localdata);
    localdata= 5;
    printf("3. Processor %d now has %d\n", rank, localdata);

    MPI_Gather(&localdata, 1, MPI_INT, globaldata, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if (rank == 0) {
        printf("4. Processor %d has data: ", rank);
        for (i=0; i<size; i++)
            printf("%d ", globaldata[i]);
        printf("\n");
    }


    MPI_Finalize();
    return 0;
}

享受学习MPI! : - )