parallel-processingmpiopenmpiscatterscatterview

MPI - scattering filepaths to processes


I have 4 filepaths in the global_filetable and I am trying to scatter 2 pilepaths to each process.

The process 0 have proper 2 paths, but there is something strange in the process 1 (null)...

EDIT: Here's the full code:

#include <stdio.h>
#include <limits.h> // PATH_MAX
#include <mpi.h>

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

    char** global_filetable = (char**)malloc(4 * PATH_MAX * sizeof(char));
    for(int i = 0; i < 4; ++i) {
        global_filetable[i] = (char*)malloc(PATH_MAX *sizeof(char));
        strncpy (filetable[i], "/path/", PATH_MAX);
    }

    /*for(int i = 0; i < 4; ++i) {
        printf("%s\n", global_filetable[i]);
    }*/

    int rank, size;

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

    char** local_filetable = (char**)malloc(2 * PATH_MAX * sizeof(char));

    MPI_Scatter(global_filetable, 2*PATH_MAX, MPI_CHAR, local_filetable, 2*PATH_MAX , MPI_CHAR, 0, MPI_COMM_WORLD);
    {

        /* now all processors print their local data: */
        for (int p = 0; p < size; ++p) {
            if (rank == p) {
                printf("Local process on rank %d is:\n", rank);
                for (int i = 0; i < 2; i++) {
                    printf("path: %s\n", local_filetable[i]);
                }
            }
            MPI_Barrier(MPI_COMM_WORLD);
        }
    }

    MPI_Finalize();
    return 0;
}

Output:

Local process on rank 0 is:
path: /path/
path: /path/
Local process on rank 1 is:
path: (null)
path: (null)

Do you have any idea why I am having those nulls?


Solution

  • First, your allocation is inconsistent:

    char** local_filetable = (char**)malloc(2 * PATH_MAX * sizeof(char));
    

    The type char** indicates an array of char*, but you allocate a contiguous memory block, which would indicate a char*.

    The easiest way would be to use the contiguous memory as char* for both global and local filetables. Depending on what get_filetable() actually does, you may have to convert. You can then index it like this:

    char* entry = &filetable[i * PATH_MAX]
    

    You can then simply scatter like this:

    MPI_Scatter(global_filetable, 2 * PATH_MAX, MPI_CHAR,
                local_filetable, 2 * PATH_MAX, MPI_CHAR, 0, MPI_COMM_WORLD);
    

    Note that there is no more displacement, every rank just gets an equal sized chunk of the contiguous memory.

    The next step would be to define a C and MPI struct encapsulating PATH_MAX characters so you can get rid of the constant usage of PATH_MAX and crude indexing.

    I think this is much nicer (less complex, less memory management) than using actual char**. You would only need that if memory waste or redundant data transfer becomes an issue.

    P.S. Make sure to never put in more than PATH_MAX - 1 characters in an filetable entry to keep space for the tailing \0.