Questions about MPI_Scatter executer & its send buffer allocation

前端 未结 1 651
轮回少年
轮回少年 2021-01-21 18:32

My first thought was MPI_Scatter and send-buffer allocation should be used in if(proc_id == 0) clause, because the data should be scattered only once a

1条回答
  •  别那么骄傲
    2021-01-21 19:06

    Your question isn't very clear, and would be a lot easier to understand if you showed some code that you were having trouble with. Here's what I think you're asking -- and I'm only guessing this because this is an error I've seen people new to MPI in C make.

    If you have some code like this:

    #include 
    #include 
    #include 
    
    int main(int argc, char **argv) {
        int proc_id, size, ierr;
        int *data;
        int recievedata;
    
        ierr = MPI_Init(&argc, &argv);
        ierr|= MPI_Comm_size(MPI_COMM_WORLD,&size);
        ierr|= MPI_Comm_rank(MPI_COMM_WORLD,&proc_id);
    
        if (proc_id == 0) {
            data = (int *)malloc(size*sizeof(int));
            for (int i=0; i\n", proc_id, recievedata);
    
        if (proc_id == 0) free(data);
    
        ierr = MPI_Finalize();
        return 0;
    }
    

    why doesn't it work, and why do you get a segmentation fault? Of course the other processes don't have access to data; that's the whole point.

    The answer is that in the non-root processes, the sendbuf argument (the first argument to MPI_Scatter()) isn't used. So the non-root processes don't need access to data. But you still can't go around dereferencing a pointer that you haven't defined. So you need to make sure all the C code is valid. But data can be NULL or completely undefined on all the other processes; you just have to make sure you're not accidentally dereferencing it. So this works just fine, for instance:

    #include 
    #include 
    #include 
    
    int main(int argc, char **argv) {
        int proc_id, size, ierr;
        int *data;
        int recievedata;
    
        ierr = MPI_Init(&argc, &argv);
        ierr|= MPI_Comm_size(MPI_COMM_WORLD,&size);
        ierr|= MPI_Comm_rank(MPI_COMM_WORLD,&proc_id);
    
        if (proc_id == 0) {
            data = (int *)malloc(size*sizeof(int));
            for (int i=0; i\n", proc_id, recievedata);
    
        if (proc_id == 0) free(data);
    
        ierr = MPI_Finalize();
        return 0;
    }
    

    If you're using "multidimensional arrays" in C, and say scattering a row of a matrix, then you have to jump through an extra hoop or two to make this work, but it's still pretty easy.

    Update:

    Note that in the above code, all routines called Scatter - both the sender and the recievers. (Actually, the sender is also a receiver).

    In the message passing paradigm, both the sender and the receiver have to cooperate to send data. In principle, these tasks could be on different computers, housed perhaps in different buildings -- nothing is shared between them. So there's no way for Task 1 to just "put" data into some part of Task 2's memory. (Note that MPI2 has "one sided messages", but even that requires a significant degree of cordination between sender and reciever, as a window has to be put asside to push data into or pull data out of).

    The classic example of this is send/recieve pairs; it's not enough that (say) process 0 sends data to process 3, process 3 also has to recieve data.

    The MPI_Scatter function contains both send and recieve logic. The root process (specified here as 0) sends out the data, and all the recievers recieve; everyone participating has to call the routine. Scatter is an example of an MPI Collective Operation, where all tasks in the communicator have to call the same routine. Broadcast, barrier, reduction operations, and gather operations are other examples.

    If you have only process 0 call the scatter operation, your program will hang, waiting forever for the other tasks to participate.

    0 讨论(0)
提交回复
热议问题