-1

I'm trying to broadcast the pointer to x to the other processors. It's declared as a global variable along with err and num. But after broadcasting, the contents of the array are incorrect for all processors except rank 0 while err and num are read correctly.

I've added comments in caps to point out what I'm referring to in the above. The bottom print loop gives the correct values of err and num after broadcasting regardless of rank but the contents of x is only correct if the rank is 0. Anyone know why?

Note: I'm not that familiar with C but the elements of the array seem to have been populated correctly as process 0 is able to access the array and read the correct elements from it.

Sample input...

3 
5.05
2 3 4

Output if I set rank to 0...

3
0.010000
0 2.000000
1 3.000000
2 4.000000

Output if I set rank to 1...

3
0.010000
0 1209010463764815312582472227618816.000000
1 18988728894356880079764586496.000000
2 78657026497739634549916490384015360.000000

and code..

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


float err; 
float *x;  // DECLARING X HERE
int num;

void get_input();  


void get_input(FILE* fp, int process_rank, int comm_size)
{
    if(process_rank == 0)
    {
        x = (float *)malloc(num * sizeof(float));

        for(int i = 0; i < num; i++) {
            fscanf(fp, "%f", &x[i]);
        }

        // BROADCASTING X
        MPI_Bcast(&x, num, MPI_FLOAT, 0, MPI_COMM_WORLD);

        fclose(fp);
    }
}


int main(int argc, char *argv[])
{
    FILE* fp;

    fp = fopen(argv[1], "r");
    if (!fp)
    {
        printf("Cannot open file %s\n", argv[1]);
        exit(1);
    }    
    fscanf(fp, "%d ", &num);
    fscanf(fp, "%f ", &err);

    int comm_size;
    int process_rank;
    x = (float *)malloc(num * sizeof(float));  /* The unknowns */

    MPI_Init(NULL, NULL);
    MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
    MPI_Comm_rank(MPI_COMM_WORLD, &process_rank);

    MPI_Bcast(&num, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&err, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);

    get_input(fp, process_rank, comm_size);

    // CHECKING X
    if(process_rank == 1) {
        printf("%d\n", num);
        printf("%f\n", err);
        for(int i = 0; i < num; i++) {
            printf("%d %f\n", i, x[i]);
        }
    }

    MPI_Finalize();

    return(0);
}
pad11
  • 311
  • 3
  • 9
  • It could be an issue with not understanding C fully as well but I thought if the variables were declared before the processors were created that they have their own copy of it? I thought that was the case for MPI but maybe I wrote things incorrectly in my notes – pad11 Apr 14 '18 at 13:35
  • Also, what do you mean by not casting? For example it's done here the same as I've seen in other sites... http://www.cs.ecu.edu/karl/3300/spr16/Notes/C/Array/heap.html – pad11 Apr 14 '18 at 13:38
  • I have not seen any other way of declaring an array on the heap so figured it was the correct way. I'm definitely not an expert at C but have to use C. As for debugging, the print statements are what I'm using for that which in this case is the very bottom where I check for process rank number. When it's 0, the elements of x are correct. When it's any other rank, the values are very large numbers. – pad11 Apr 14 '18 at 13:48
  • :) "Allocating an array in C (optional)" - the website mentions this and shows the same syntax. That's what I was referring to sorry. It's also the same syntax that the professor used in his skeleton script – pad11 Apr 14 '18 at 13:49
  • 1
    Your question is really about MPI, so you do not need the `C` tag. Some folks have a strong opinion about whether `malloc()` result should be casted or not, https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc lists pros and cons. – Gilles Gouaillardet Apr 14 '18 at 14:26
  • Ok thanks! I'll read later on what you guys were referring to :) – pad11 Apr 14 '18 at 14:49

1 Answers1

1

The first argument of MPI_Bcast() is a pointer to a buffer, and not the address of a pointer to a buffer.

So you need to replace MPI_Bcast(&x, ...); with MPI_Bcast(x, ...);

You also need to allocate x and MPI_Bcast() on all ranks. Here is the corrected get_input() function

void get_input(FILE* fp, int process_rank, int comm_size)
{
    x = (float *)malloc(num * sizeof(float));

    if(process_rank == 0)
    {
        for(int i = 0; i < num; i++) {
            fscanf(fp, "%f", &x[i]);
        }
    }

    // BROADCASTING X
    MPI_Bcast(x, num, MPI_FLOAT, 0, MPI_COMM_WORLD);

    fclose(fp);
}

That being said, you might want to revamp your code so only rank 0 open/read/close the input file.

Gilles Gouaillardet
  • 8,193
  • 11
  • 24
  • 30