0

I'm a newby in MPI and I'm trying to learn how to use MPI_Type_create_subarray in order to apply it in my projects. I've spent lots of time searching for a tutorial which could fits my needing, but without success.

So I've tried to generalize the concept in How to use MPI_Type_create_subarray to 3D arrays, but something is still missing.

In particular my code return a Segmentation Fault error or shows wrong data when I try to see results. I can't understand where I made a mistake

This is my code:

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

void printarr(int ***data, int nx, int ny, int nz, char *str);
int ***allocarray(int nx, int ny, int nz);

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

/* array sizes */
const int bigsize =10;
const int subsize_x =2;      const int subsize_y =2;     const int subsize_z =2;

/* communications parameters */
const int sender  =0;
const int receiver=1;
const int ourtag  =2;

int rank, size;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);

if (size < receiver+1) {
    if (rank == 0)
        fprintf(stderr,"%s: Needs at least %d  processors.\n", argv[0], receiver+1);
    MPI_Finalize();
    return 1;
}


MPI_Datatype mysubarray;

int starts[3] = {0,0,0};
int subsizes[3]  = {subsize_x,subsize_y,subsize_z};
int bigsizes[3]  = {bigsize, bigsize, 3};
MPI_Type_create_subarray(3, bigsizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &mysubarray);
MPI_Type_commit(&mysubarray);

if (rank == sender) {
    int ***bigarray = allocarray(bigsize,bigsize,3);
    for (int k=0; k<3; k++)
        for (int j=0; j<bigsize; j++)
            for(int i=0; i< bigsize; i++) {
                bigarray[k][j][i] = k*(bigsize*bigsize)+j*bigsize+i;
            }

    printarr(bigarray, bigsize, bigsize, 3, " Sender: Big array ");

    MPI_Send(&(bigarray[0][0][0]), 1, mysubarray, receiver, ourtag, MPI_COMM_WORLD);
    MPI_Type_free(&mysubarray);

    free(bigarray);

} else if (rank == receiver) {

    int ***subarray = allocarray(subsize_x,subsize_y,subsize_z);
    MPI_Recv(&(subarray[0][0][0]), subsizes[0]*subsizes[1]*subsizes[2], MPI_INT, sender, ourtag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

    printarr(subarray, subsize_x, subsize_y, subsize_z, " Receiver: Subarray -- after receive");

    free(subarray);
}

MPI_Finalize();
return 0;
}

void printarr(int ***data, int nx, int ny, int nz, char *str) {
printf("-- %s --\n", str);
for(int k=0; k<nz; k++) {
    printf("\n\n-----%d------\n",k);
    for (int j=0; j<ny;j++) {
        for (int i=0; i<nx; i++) {
            printf("%3d ", data[k][j][i]);
        }
    printf("\n");
    }
}
}

int ***allocarray(int nx, int ny, int nz) {

int*** arr = (int***)malloc(sizeof(int**)*nz);
for(int k = 0; k < nz; k++) {
    arr[k]= (int**)malloc(sizeof(int*)*ny);
    for(int j = 0; j< ny; j++){
        arr[k][j] = (int*)malloc(sizeof(int)*nx);
        for(int i = 0; i < nx; i++){
            arr[k][j][i] = 0;
        }
    }
}
return arr;
}
9
  • What you call a 3D-array in fact is one 1D-array of nz int** elements plus nz 1D-arrays of ny int* elements plus nz*ny int arrays of nx int elements. All in all 1+nz+nz*ny 1D arrays, each being an isolated single chunk of memory on its own, as opposed to a real 3D-array which would be one array, that is one chunk of continuous memory. Commented Jan 26, 2019 at 12:45
  • Ok, I've understood my fault. Anyway the bigarray of my application (the real ones, not the one in this example) is 256*512*1024*2 double entries wide, so it's mandatory for me to allocate it dynamically. Can you suggest me a declaration which could fits my needing? Or another way to scatter the data properly among all my processors ? Commented Jan 26, 2019 at 13:26
  • Understand the difference between your allocarray and analogue function given by the example you linked. The example in fact allocates one chunk of memory holding all ints: int *data = malloc(n*n*sizeof(int)); Commented Jan 26, 2019 at 13:32
  • "256*512*1024*2" a 4D-array? Commented Jan 26, 2019 at 13:34
  • @alk Thank you for the explanation, anyway the 2 is to account the fact that are complex numbers. I must use it because, later in my code, I employ a library which can handle complex just in this way Commented Jan 26, 2019 at 13:50

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.