【问题标题】:How to sum a 2D array in C using MPI如何使用 MPI 在 C 中对二维数组求和
【发布时间】:2021-03-25 19:41:16
【问题描述】:

这是我用来对一维数组中的所有值求和的程序,它工作正常。但是如何修改它以在二维数组上工作?想象变量a 类似于a = { {1,2}, {3,4}, {5,6} };

我尝试了一些解决方案,但它们都不起作用,所以有人可以解释一些重要的更改以使其也与 2D 数组兼容。

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

// size of array
#define n 10

int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// Temporary array for slave process
int a2[1000];

int main(int argc, char* argv[])
{

    int pid, np,
        elements_per_process,
        n_elements_recieved;
    // np -> no. of processes
    // pid -> process id

    MPI_Status status;

    // Creation of parallel processes
    MPI_Init(&argc, &argv);

    // find out process ID,
    // and how many processes were started
    MPI_Comm_rank(MPI_COMM_WORLD, &pid);
    MPI_Comm_size(MPI_COMM_WORLD, &np);

    // master process
    if (pid == 0) {

        int index, i;
        elements_per_process = n / np;

        // check if more than 1 processes are run
        if (np > 1) {
            // distributes the portion of array
            // to child processes to calculate
            // their partial sums
            for (i = 1; i < np - 1; i++) {
                index = i * elements_per_process;

                MPI_Send(&elements_per_process,
                    1, MPI_INT, i, 0,
                    MPI_COMM_WORLD);
                MPI_Send(&a[index],
                    elements_per_process,
                    MPI_INT, i, 0,
                    MPI_COMM_WORLD);
            }
            // last process adds remaining elements
            index = i * elements_per_process;
            int elements_left = n - index;

            MPI_Send(&elements_left,
                1, MPI_INT,
                i, 0,
                MPI_COMM_WORLD);
            MPI_Send(&a[index],
                elements_left,
                MPI_INT, i, 0,
                MPI_COMM_WORLD);
        }

        // master process add its own sub array
        int sum = 0;
        for (i = 0; i < elements_per_process; i++) 
            sum += a[i];

        // collects partial sums from other processes
        int tmp;
        for (i = 1; i < np; i++) {
            MPI_Recv(&tmp, 1, MPI_INT,
                MPI_ANY_SOURCE, 0,
                MPI_COMM_WORLD,
                &status);
            int sender = status.MPI_SOURCE;
            sum += tmp;
        }

        // prints the final sum of array
        printf("Sum of array is : %d\n", sum);



    }
    // slave processes
    else {
        MPI_Recv(&n_elements_recieved,
            1, MPI_INT, 0, 0,
            MPI_COMM_WORLD,
            &status);

        // stores the received array segment
        // in local array a2
        MPI_Recv(&a2, n_elements_recieved,
            MPI_INT, 0, 0,
            MPI_COMM_WORLD,
            &status);

        // calculates its partial sum
        int partial_sum = 0;
        for (int i = 0; i < n_elements_recieved; i++)
            partial_sum += a2[i];

        // sends the partial sum to the root process
        MPI_Send(&partial_sum, 1, MPI_INT,
            0, 0, MPI_COMM_WORLD);
    }

    // cleans up all MPI state before exit of process
    MPI_Finalize();




    return 0;
}

【问题讨论】:

    标签: c performance parallel-processing mpi hpc


    【解决方案1】:

    你可以通过使用MPI_Reduce而不是MPI_Send/MPI_Recv来简化很多:

    将所有进程的值减少为单个值

    可以在here 找到有关该例程的精彩教程。

    因此每个进程都包含一个数组(例如进程 0 { 1, 2, 3, 4, 5} 和进程 1 {6, 7, 8, 9, 10 })并执行该数组的部分求和。最后,每个进程使用MPI_Reduce 将所有部分总和汇总为一个可供主进程使用的单个值(它也可能是另一个进程)。看看这个例子:

    #include <mpi.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char* argv[]){
        int np, pid;
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &pid);
        MPI_Comm_size(MPI_COMM_WORLD, &np);
    
        int partial_sum = 0;
        if (pid == 0) {
            int a[] = { 1, 2, 3, 4, 5};
            for(int i = 0; i < 5; i++)
               partial_sum += a[i];        
        }
        else  if (pid == 1){
            int a[] = {6, 7, 8, 9, 10};
            for(int i = 0; i < 5; i++) 
               partial_sum += a[i];
        }
        int sum;
        MPI_Reduce(&partial_sum, &sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
    
        if (pid == 0){
           printf("Sum of array is : %d\n", sum);
        }
     
        MPI_Finalize();
        return 0;
    }
    

    此代码仅适用于 2 个进程(这有点傻(但我用它来展示 MPI_Reduce 的使用。

    我尝试了一些解决方案,但它们都不起作用,所以有人可以解释一下 需要进行一些重要更改以使其与 2D 数组兼容 也。

    如果您调整代码以使用MPI_Reduce,如我所展示的,那么它是一维数组还是二维数组都没有关系,因为您将首先将部分总和转换为单个值,然后执行缩减。

    或者,您也可以将每一行分配给一个进程,然后执行整个数组的归约,然后 master 进程执行结果数组的总和。

    一个例子:

    #include <mpi.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char* argv[]){
        int np, pid;
        MPI_Status status;
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &pid);
        MPI_Comm_size(MPI_COMM_WORLD, &np);
    
        int partial_sum = 0;
        int size = 5;
        int a[5] = {1, 2, 3 , 4, 5};
        int sum[5] = {0};
        MPI_Reduce(&a, &sum, size, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
    
        if (pid == 0){
           int total_sum = 0;
           for(int i = 0; i < size; i++)
               total_sum += sum[i];
           printf("Sum of array is : %d\n", total_sum);
        }
    
        MPI_Finalize();
        return 0;
    }
    

    输出(用于两个进程):

    Sum of array is : 30
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-05
      • 2014-06-23
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 1970-01-01
      相关资源
      最近更新 更多