c - 如何通过数组使用 MPI 分散和聚集

标签 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;
}

最佳答案

你的设置和分散原则上是没问题的。您的问题在于打印,因为您在这里误解了分散/聚集的细节。

当分散 4 元素数组时,每个进程仅获取一个元素(正如您使用 MPI_Scatter call() 的第二个和第五个参数定义的那样)。该元素存储在本地数组的 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 的乐趣! :-)

关于c - 如何通过数组使用 MPI 分散和聚集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40080362/

相关文章:

c - 罗马数字翻译器中的随机加法

C - 时间值到 uint64_t

c - 在 C 中手动从递归获取输出

c - setlocale() 使用哪些文件?

sql - 为什么我似乎不能强制Oracle 11g为单个SQL查询消耗更多的CPU

python - 双调排序,mpi4py

c - 异常行为字符串 MPI_Send() 和 MPI_Recv()

python - 如何同时运行2个不同的进程?

erlang - 当它们同时传递消息时,为什么MPI比共享内存更难,而Erlang则更容易?

c++ - boost::mpi 作为模板类的静态成员