1

I'm just starting out with MPI programming and decided to make a simple distributed qsort using OpenMPI. To distribute parts of the array I want to sort I'm trying to use MPI_Scatterv, however the following code segfaults on me:

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <mpi.h> #define ARRAY_SIZE 26 #define BUFFER_SIZE 2048 int main(int argc, char** argv) { int my_rank, nr_procs; int* data_in, *data_out; int* sizes; int* offsets; srand(time(0)); MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &nr_procs); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); // everybody generates the control tables int nr_workers = nr_procs-1; sizes = malloc(sizeof(int)*nr_workers); offsets = malloc(sizeof(int)*nr_workers); int nr_elems = ARRAY_SIZE/nr_workers; // basic distribution for (int i = 0; i < nr_workers; ++i) { sizes[i] = nr_elems; } // distribute the remainder int left = ARRAY_SIZE%nr_workers; int curr_worker = 0; while (left) { ++sizes[curr_worker]; curr_worker = (++curr_worker)%nr_workers; --left; } // offsets int curr_offset = 0; for (int i = 0; i < nr_workers; ++i) { offsets[i] = curr_offset; curr_offset += sizes[i]; } if (my_rank == 0) { // root data_in = malloc(sizeof(int)*ARRAY_SIZE); data_out = malloc(sizeof(int)*ARRAY_SIZE); for (int i = 0; i < ARRAY_SIZE; ++i) { data_in[i] = rand(); } for (int i = 0; i < nr_workers; ++i) { printf("%d at %d\n", sizes[i], offsets[i]); } MPI_Scatterv (data_in, sizes, offsets, MPI_INT, data_out, ARRAY_SIZE, MPI_INT, 0, MPI_COMM_WORLD); } else { // worker printf("%d has %d elements!\n",my_rank, sizes[my_rank-1]); // alloc the input buffer data_in = malloc(sizeof(int)*sizes[my_rank-1]); MPI_Scatterv(NULL, NULL, NULL, MPI_INT, data_in, sizes[my_rank-1], MPI_INT, 0, MPI_COMM_WORLD); printf("%d got:\n", my_rank); for (int i = 0; i < sizes[my_rank-1]; ++i) { printf("%d ", data_in[i]); } printf("\n"); } MPI_Finalize(); return 0; } 

How would I go about using Scatterv? Am I doing something wrong with allocating my input buffer from inside the worker code?

1 Answer 1

1

I changed some part in your code to get something working.

MPI_Scatter() will send data to every processors, including himself. According to your program, processor 0 expects ARRAY_SIZE integers, but sizes[0] is much smaller. There are other problems on other processus : MPI_Scatter will send sizes[my_rank] integers, but sizes[my_rank-1] will be expected...

Here is a code that scatters data_in from 0 to all processors, including 0. Therefore i added 1 to nr_workers :

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <mpi.h> #define ARRAY_SIZE 26 #define BUFFER_SIZE 2048 int main(int argc, char** argv) { int my_rank, nr_procs; int* data_in, *data_out; int* sizes; int* offsets; srand(time(0)); MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &nr_procs); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); // everybody generates the control tables int nr_workers = nr_procs; sizes = malloc(sizeof(int)*nr_workers); offsets = malloc(sizeof(int)*nr_workers); int nr_elems = ARRAY_SIZE/nr_workers; // basic distribution for (int i = 0; i < nr_workers; ++i) { sizes[i] = nr_elems; } // distribute the remainder int left = ARRAY_SIZE%nr_workers; int curr_worker = 0; while (left) { ++sizes[curr_worker]; curr_worker = (++curr_worker)%nr_workers; --left; } // offsets int curr_offset = 0; for (int i = 0; i < nr_workers; ++i) { offsets[i] = curr_offset; curr_offset += sizes[i]; } if (my_rank == 0) { // root data_in = malloc(sizeof(int)*ARRAY_SIZE); for (int i = 0; i < ARRAY_SIZE; ++i) { data_in[i] = rand(); printf("%d %d \n",i,data_in[i]); } for (int i = 0; i < nr_workers; ++i) { printf("%d at %d\n", sizes[i], offsets[i]); } } else { printf("%d has %d elements!\n",my_rank, sizes[my_rank]); } data_out = malloc(sizeof(int)*sizes[my_rank]); MPI_Scatterv (data_in, sizes, offsets, MPI_INT, data_out, sizes[my_rank], MPI_INT, 0, MPI_COMM_WORLD); printf("%d got:\n", my_rank); for (int i = 0; i < sizes[my_rank]; ++i) { printf("%d ", data_out[i]); } printf("\n"); free(data_out); if(my_rank==0){ free(data_in); } MPI_Finalize(); return 0; } 

Regarding memory managment, data_in and data_out should be freed at the end of the code.

Is it what you wanted to do ? Good luck with qsort ! I think you are not the first one to sort integers using MPI. See parallel sort using mpi. Your way to generate random numbers on the 0 processus and then scatter them is the right way to go. I think you will be interrested by his TD_Trier() function for communication. Even if you change tri_fusion(T, 0, size - 1); for qsort(...)...

Bye,

Francis

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for the explanation and useful tips! As a beginner I find documentation regarding MPI pretty lacking - sure there are a lot of references, but most of the material is pretty poorly explained. It didn't even occur to me, that the root process sends data to itself too (which in hindsight makes perfect sense). Sadly I cannot +rep you for your contribution, because I'm too new :(
I'm not Deino, but I do like his reference pages about MPI. You might try giving it a look. mpi.deino.net/mpi_functions/MPI_Scatter.html

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.