簡體   English   中英

如何使用 MPI 對 C 中的二維數組求和

[英]How to sum a 2D array in C using MPI

這是我用來對一維數組中的所有值求和的程序,它工作正常。 但是如何修改它以在二維數組上工作? 想象變量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;
}

您可以通過使用MPI_Reduce而不是MPI_Send / MPI_Recv來簡化很多:

將所有流程的值減少到單個值

可以在此處找到有關該例程的不錯的教程。

因此,每個進程都包含一個數組(例如,進程 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 ,那么它是 1D 還是 2D 數組並不重要,因為您將首先將部分總和轉換為單個值,然后執行縮減。

或者,您也可以將每一行分配給一個進程,然后執行整個數組的歸約,然后進程執行結果數組的總和。

一個例子:

#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;
}

Output(用於兩個進程):

Sum of array is : 30

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM