MergeSort MPI: mpirun -np 4 --allow-run-as- root a.out не работает - PullRequest
0 голосов
/ 19 июня 2020

У меня небольшая проблема с упражнением «Сортировка слиянием с MPI». если я компилирую с использованием «mpirun -np 2 --allow-run-as- root a.out», он работает правильно, но если я компилирую с использованием «mpirun -np 4 --allow-run-as- root a .out "я получил странный вектор: 1 1 2 4 7 8 11 15 0 4 6 6 8 8 10 10, и он упорядочен до половины. вы можете помочь мне понять почему? спасибо

#include "mpi.h"
using namespace std;
#include <iostream>
#include <cmath>
//void merge(int *, int *, int);

#define n 16

void mergeSort(int *recdata, int buf)
{
    int meta = buf / 2;
    if (meta > 0)
    {
        mergeSort(recdata, meta);              //analizzo prima meta' dell'array
        mergeSort(recdata + meta, buf - meta); //analizzo seconda meta' dell'array

        //classico merge sort
        int *tmp = new int[buf];

        int i = 0;
        int k = 0;
        int j = meta;
        while (i < meta && j < buf)
        {
            if (recdata[i] < recdata[j])
            {
                tmp[k] = recdata[i];
                i++;
            }
            else
            {
                tmp[k] = recdata[j];
                j++;
            }
            k++;
        }

        while (i < meta)
        {
            tmp[k] = recdata[i];
            k++;
            i++;
        }

        while (j < buf)
        {
            tmp[k] = recdata[j];
            k++;
            j++;
        }

        for (i = 0; i < buf; i++)
            recdata[i] = tmp[i];
        delete[] tmp;
    }
}

int main(int argc, char *argv[])
{
    int myid;
    int numprocs;
    int buf;
    double timer_start;
    double timer_end;

    MPI_Request req;

    MPI_Status status;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    int *data;
    buf = n / numprocs; //buf e' il numero di elementi cha avra' ogni processo
    if (myid == 0)
    {
        data = new int[n];
        cout << endl
             << "Array disordinato: ";
        srand(time(NULL));
        for (int i = 0; i < n; i++)
        {
            data[i] = rand() % n;
            cout << data[i] << " ";
        }

        timer_start = MPI_Wtime();

        cout << endl
             << endl;
    }

    int *recdata = new int[n]; //array vuoto che mi permette di conservare tutti i dati divisi sui vari processi
    // prendo struttura dati e la mando a tutti i processi

    // data contiene tutti i numeri, buf e' la quantita' di numeri da mandare
    //int MPI_Scatter(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
    //                 void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
    //          data e' l'array originale che contine numeri disordinati, buf e' il numero di elementi che ogni vettore riceve
    //          recdata e' il nuovo array che deve contenere i numeri ricevuti
    MPI_Scatter(data, buf, MPI_INT, recdata, buf, MPI_INT, 0, MPI_COMM_WORLD);

    //local sort
    mergeSort(recdata, buf);

    bool u = true;

    while (u)
    {
        if (myid % 2 == 0)
        {
            //mando il max
            int min;
            //             mando                                    ricevo
            MPI_Sendrecv(&recdata[buf - 1], 1, MPI_INT, myid + 1, 0, &min, 1, MPI_INT, myid + 1, 0, MPI_COMM_WORLD, &status);
            //MPI_Recv(&min, 1, MPI_INT, myid + 1, 0, MPI_COMM_WORLD, &status);
            if (min < recdata[buf - 1])
            {
                recdata[buf - 1] = min;
                mergeSort(recdata, buf);
            }
            else
                u = false;
        }
        else
        {
            //mando il minimo
            int max;
            //             mando                                    ricevo
            MPI_Sendrecv(&recdata[0], 1, MPI_INT, myid - 1, 0, &max, 1, MPI_INT, myid - 1, 0, MPI_COMM_WORLD, &status);

            if (max > recdata[0])
            {
                recdata[0] = max;
                mergeSort(recdata, buf);
            }
            else
                u = false;
        }
    }
    /*int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
               void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)*/
    MPI_Gather(recdata, buf, MPI_INT, data, buf, MPI_INT, 0, MPI_COMM_WORLD);

    if (myid == 0)
    {
        cout << endl
             << "Array ordinato: " << endl;
        for (int i = 0; i < n; i++)
            cout << data[i] << " ";

        cout << endl
             << endl;

        timer_end = MPI_Wtime();

        cout << endl
             << endl
             << "Time: " << timer_end - timer_start << endl
             << endl;
    }

    MPI_Finalize();
    return 0;
}
...