-2

I'm doing a project for a class and I have used the code for sequential Bucket sort from the internet and I'm trying to make it be a parallel version using OpenMPI. This code will be running on the cluster system. When I test it, it is giving me the following error:

"[cluster:5379] * An error occurred in MPI_Send [cluster:5379] on communicator MPI_COMM_WORLD [cluster:5379] MPI_ERR_RANK: invalid rank [cluster:5379] * MPI_ERRORS_ARE_FATAL: your MPI job will now abort "

Can anybody please suggest me on how to fix it?

ps. I'm quite bad at coding, so I might not be able to answers some question for this.

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

struct bucket
{
    int count;
    int* value;
};

int compareIntegers(const void* first, const void* second)
{
    int x = *((int*)first), y = *((int*)second);
    if (x == y)
    {
        return 0;
    }
    else if (x < y)
    {
        return -1;
    }
    else
    {
        return 1;
    }
}

void bucketSort(int array[], int n)
{
    struct bucket buckets[3];
    int i, j, k;
    for (i = 0; i < 3; i++)
    {
        buckets[i].count = 0;
        buckets[i].value = (int*)malloc(sizeof(int) * n);
    }

    for (i = 0; i < n; i++)
    {
        if (array[i] < 0)
        {
            buckets[0].value[buckets[0].count++] = array[i];
        }
        else if (array[i] > 10)
        {
            buckets[2].value[buckets[2].count++] = array[i];
        }
        else
        {
            buckets[1].value[buckets[1].count++] = array[i];
        }
    }
    for (k = 0, i = 0; i < 3; i++)
    {
        // now using quicksort to sort the elements of buckets
        qsort(buckets[i].value, buckets[i].count, sizeof(int), &compareIntegers);
        for (j = 0; j < buckets[i].count; j++)
        {
            array[k + j] = buckets[i].value[j];
        }
        k += buckets[i].count;
        free(buckets[i].value);
    }

}

int main(char *argv[], int argc)
{
    int array[1000000];
    int i = 0, j, k, n;
    int num;
    //for MPI
    int numProc, rank;
    char procName[MPI_MAX_PROCESSOR_NAME];
    int nameLen;
    int chunksize;
    double start, end;
    int msgtag;

    //MPI
    MPI_Status stat;
    start = MPI_Wtime();    //timer start
    MPI_Init(&argc, &argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &rank); //process rank ,comm_world = communication of the process
    MPI_Comm_size(MPI_COMM_WORLD, &numProc); //number of process
    msgtag = 1234;

    if (rank == 0)
    {
        printf("Enter number of element to be sort: ");
        scanf("%d", &num);

        for (i = 0; i < num; i++) //random num elements
        {
            array[i] = rand();
        }

        n = i;
        printf("\nBefore Sorting\n");
        for (j = 0; j < i; j++)
        {
            printf("%d ", array[j]);
        }
        MPI_Send(&array[j], j, MPI_INT, 1, msgtag, MPI_COMM_WORLD);
    }

    if (rank == 1)
    {
        MPI_Recv(&array[j], j, MPI_INT, 0, msgtag, MPI_COMM_WORLD, &stat);
        bucketSort(array, n);
        MPI_Send(&array, n, MPI_INT, 2, msgtag, MPI_COMM_WORLD);
    }

    if (rank == 2)
    {
        MPI_Recv(&array, n, MPI_INT, 1, msgtag, MPI_COMM_WORLD, &stat);
        printf("\nAfter Sorting\n");
        for (k = 0; k < i; k++)
        {
            printf("%d ", array[k]);
        }
    }
    //MPI END
    MPI_Finalize();
    end = MPI_Wtime();  // timer end   
    double time_spent = end - start;
    printf("\ntime used for this program was %f Sec.", time_spent);

    return 0;
}
PilouPili
  • 2,601
  • 2
  • 17
  • 31
kukiduwa
  • 11
  • 1
  • 4
  • 4
    Please format (e.g. indent) your code correctly ! SO is not a free debugging service, so please trim your program into a [MCVE] and share your efforts. – Gilles Gouaillardet Oct 10 '18 at 22:06

1 Answers1

0

they are quite a few mistakes in your code. Hope due date is monday…

First :

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

will work better than int main(int argc, char *argv[])

Second :

Process 0 is the one designated to read the number of elements to be generated.
Then it must brodacast it to all other process otherwise the other processes will have an undefined number in variable num, right ?

Therefore

if (rank == 0)
{
        printf("Enter number of element to be sort: ");
        fflush(stdout);
        scanf("%d", &num);
        for (i = 0; i < num; i++) //random num elements
    {
        array[i] = rand();
    }
        n = num;
        printf("\nBefore Sorting (%i)\n", n);
    for (j = 0; j < n; j++)
    {
        printf("%d ", array[j]);
    }
        fflush(stdout);
}
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

Third :

Avoid reusing the value involved in loop. I understand that after

for (j = 0; j < n; j++)
{
    printf("%d ", array[j]);
}

you have

j=n

but it is not very clear…

Fourth :

First argument to MPI_Send or receive is the adress of the first element in the array. So passing

MPI_Send(&array[j], j, MPI_INT, 1, msgtag, MPI_COMM_WORLD);

and since j=n (see remark above) I guess you won't get what you desire.

What you need is

MPI_Send(&array[0], n, MPI_INT, 1, msgtag, MPI_COMM_WORLD);

Fifth :

MPI_Barrier is your friend. Outputing is a critical operation therefore before an output operation you can (optional) make sure that all processes have reached this point.

if (rank == 2)
{
    MPI_Recv(&array, n, MPI_INT, 1, msgtag, MPI_COMM_WORLD, &stat);
    printf("\nAfter Sorting\n");
    for (k = 0; k < i; k++)
    {
        printf("%d ", array[k]);
    }
}

becomes

if (rank == 2)
{
    MPI_Recv(&(array[0]), n, MPI_INT, 1, msgtag, MPI_COMM_WORLD, &stat);
}
MPI_Barrier(MPI_COMM_WORLD);
if (rank == 2)
{
    printf("\nAfter Sorting\n");
    for (k = 0; k < n; k++)
    {
        printf("%d ", array[k]);
    }
}
    MPI_Barrier(MPI_COMM_WORLD);

Conclusion :

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

struct bucket
{
    int count;
    int* value;
};

int compareIntegers(const void* first, const void* second)
{
    int x = *((int*)first), y = *((int*)second);
    if (x == y)
    {
        return 0;
    }
    else if (x < y)
    {
        return -1;
    }
    else
    {
        return 1;
    }
}

void bucketSort(int array[], int n)
{
    struct bucket buckets[3];
    int i, j, k;
    for (i = 0; i < 3; i++)
    {
        buckets[i].count = 0;
        buckets[i].value = (int*)malloc(sizeof(int) * n);
    }

    for (i = 0; i < n; i++)
    {
        if (array[i] < 0)
        {
            buckets[0].value[buckets[0].count++] = array[i];
        }
        else if (array[i] > 10)
        {
            buckets[2].value[buckets[2].count++] = array[i];
        }
        else
        {
            buckets[1].value[buckets[1].count++] = array[i];
        }
    }
    for (k = 0, i = 0; i < 3; i++)
    {
        // now using quicksort to sort the elements of buckets
        qsort(buckets[i].value, buckets[i].count, sizeof(int), &compareIntegers);
        for (j = 0; j < buckets[i].count; j++)
        {
            array[k + j] = buckets[i].value[j];
        }
        k += buckets[i].count;
        free(buckets[i].value);
    }

}

int main(int argc, char *argv[])
{
    int array[1000000];
    int i = 0, j, k, n;
    int num;
    //for MPI
    int numProc, rank;
    char procName[MPI_MAX_PROCESSOR_NAME];
    int nameLen;
    int chunksize;
    double start, end;
    int msgtag;

    //MPI
    MPI_Status stat;
    start = MPI_Wtime();    //timer start
    MPI_Init(&argc, &argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &rank); //process rank ,comm_world = communication of the process
    MPI_Comm_size(MPI_COMM_WORLD, &numProc); //number of process
    msgtag = 1234;

    if (rank == 0)
    {
        printf("Enter number of element to be sort: ");
        fflush(stdout);
        scanf("%d", &num);
        for (i = 0; i < num; i++) //random num elements
        {
            array[i] = rand();
        }
        n = num;
        printf("\nBefore Sorting\n");
        for (j = 0; j < n; j++)
        {
            printf("%d ", array[j]);
        }
        fflush(stdout);
    }
    MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
    if (rank == 0)
    {
        MPI_Send(&(array[0]), n, MPI_INT, 1, msgtag, MPI_COMM_WORLD);
    }
    if (rank == 1)
    {
        MPI_Recv(&(array[0]), n, MPI_INT, 0, msgtag, MPI_COMM_WORLD, &stat);
        bucketSort(array, n);
        MPI_Send(&(array[0]), n, MPI_INT, 2, msgtag, MPI_COMM_WORLD);
    }
    if (rank == 2)
    {
        MPI_Recv(&(array[0]), n, MPI_INT, 1, msgtag, MPI_COMM_WORLD, &stat);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    if (rank == 2)
    {
        printf("\nAfter Sorting\n");
        for (k = 0; k < n; k++)
        {
            printf("%d ", array[k]);
        }
    }
    //MPI END
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
    end = MPI_Wtime();  // timer end   
    double time_spent = end - start;
    printf("\ntime used for this program was %f Sec.", time_spent);

    return 0;
}

running

mpirun -np 3 test_mpi.exe

outputs

Enter number of element to be sort: 10

Before Sorting
1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
After Sorting

424238335 596516649 719885386 846930886 1189641421 1649760492 1681692777 1714636915 1804289383 1957747793
time used for this program was 2.271976 Sec.time used for this program was 2.281183 Sec.
time used for this program was 2.277746 Sec.
PilouPili
  • 2,601
  • 2
  • 17
  • 31