Mpi с C, используя mpi_comm_spawn(), не может запустить последнюю программу

#c #ubuntu #process #mpi #spawn

#c #ubuntu #процесс #mpi #спавн

Вопрос:

Я реализовал следующий код на C:

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

struct fields{
   int hostNumber;
   int *numberArray;
};

struct fields *start(int, int);
struct fields *gatherData(int, int);

int main(int argc, char** argv) {
    int rank, size, tmpNmb1, tmpNmb2, 
            notOrderedFlag = 0, tmpI = 0,
            nbFinalArray, tmpRetrieveArray[3],
            count, row1 = 0, col1 = 0;
    struct fields *myFields;
    MPI_Status status;
    setbuf(stdout, NULL);
    
    MPI_Init(amp;argc, amp;argv);
    MPI_Comm_rank(MPI_COMM_WORLD, amp;rank);
    MPI_Comm_size(MPI_COMM_WORLD, amp;size);   

    if (rank == 0){                   
        myFields = start(rank, size);
        //for (int i = 0 ; i < myFields->hostNumber ; i  ) printf("%dn",((myFields->numberArray)[i]));          
        if ((myFields->hostNumber) < size){
            printf("Error!!! Number of Processes is more than number of Elements.n");
          
            MPI_Abort(MPI_COMM_WORLD, 0); 
        }

        if (myFields->hostNumber < (2 * size)){
            printf("Error!!! The Host of Numbers should be at least double of the number  of Processes!!!n");
     
            MPI_Abort(MPI_COMM_WORLD, 0); 
        }

        for (int i = 1; i < size; i  ){ 
            MPI_Send(amp;(myFields->hostNumber), 1, MPI_INT,  i, 1000, MPI_COMM_WORLD); 
            MPI_Send(myFields->numberArray, myFields->hostNumber, MPI_INT, i, 1001, MPI_COMM_WORLD);
        }
        
  
    }   

    if (rank != 0){
        myFields = (struct fields *)malloc(sizeof(struct fields));
        if (myFields == NULL){
            printf("Error while allocating memory for myFields structure!!!n");
         
            MPI_Abort(MPI_COMM_WORLD, 0);                                  
        }

        MPI_Recv((amp;(myFields->hostNumber)), 1, MPI_INT, 0, 1000, MPI_COMM_WORLD, amp;status);
        MPI_Get_count(amp;status, MPI_INT, amp;count);
        //printf("Process %d received %d int(s) from Process %d with tag %d n", rank, count, status.MPI_SOURCE, status.MPI_TAG);
        //printf("number = %dn", myFields->hostNumber);

        myFields->numberArray = (int *)malloc(sizeof(struct fields) * (myFields->hostNumber));
        MPI_Recv((myFields->numberArray), (myFields-> hostNumber), MPI_INT, 0, 1001, MPI_COMM_WORLD, amp;status); //Why this is not running?
        MPI_Get_count(amp;status, MPI_INT, amp;count);            
        //printf("Process %d received %d int(s) from Process %d with tag %d n", rank, count, status.MPI_SOURCE, status.MPI_TAG);

        /*for (int i = 0 ; i < myFields->hostNumber ; i  ){
            printf("%dn",(*(myFields->numberArray)));
            (myFields->numberArray)  ;
        }*/

        /*for (int i = 0 ; i < myFields->hostNumber ; i  ){
            printf("%dn",((myFields->numberArray)[i]));
        }*/
    }

    tmpNmb1 = ((myFields->hostNumber) / size);
    tmpNmb2 = ((myFields->hostNumber) % size);
    int row = (rank * tmpNmb1);    
    //printf("tmpNb1=%dn",tmpNmb1);
    //printf("tmpNb2=%dn",tmpNmb2);
    //printf("row=%dn",row);

    if (tmpNmb2 == 0){
        nbFinalArray = size;
    }
    else{
        nbFinalArray = (size   1);
    }

    int finalArray[nbFinalArray];
    int retrieveArray[size - 1][3];

    for (int i = row ; i < ((row   tmpNmb1) - 1); i  ){
        if (((myFields->numberArray)[i]) <= ((myFields->numberArray)[i 1])){
            notOrderedFlag = 0; //Ordered
            if (rank == 0) finalArray[rank] = myFields->numberArray[tmpNmb1 -1];
        } 
        else{
            notOrderedFlag = 1; // Not Ordered
            tmpI = i;
            break;
        } 
    }    

    if (notOrderedFlag == 1){
        if (rank == 0){
            printf("From Proccess 0 - Position %d. The Array is not Ordered!n", tmpI);
      
            MPI_Abort(MPI_COMM_WORLD, 0);
        }
        else if (rank != 0){                
            int tmpArray[3] = {rank, notOrderedFlag, tmpI};
            MPI_Send(tmpArray, 3, MPI_INT,  0, 1000, MPI_COMM_WORLD); //wrong Array
        }
    }

    if (rank == 0){
        for (int i = 1; i < size ; i  ){
            MPI_Recv(tmpRetrieveArray, 3, MPI_INT, i, 1000, MPI_COMM_WORLD, amp;status);
            MPI_Get_count(amp;status, MPI_INT, amp;count);
            //printf("Process %d received %d int(s) from Process %d with tag %d n", rank, count, status.MPI_SOURCE, status.MPI_TAG);
            //for (int i = 0; i < 3; i  ) printf("Array[%d] = %dn", i, tmpRetrieveArray[i]);
            for (int j = 0; j < 3; j   ){
                retrieveArray[row1][col1] = tmpRetrieveArray[j];
                col1  ;
            }
            row1  ;
            col1 = 0;                
        }
        row1 = col1 = 0;
        /*for (int i = 0 ;i < (size-1);i  ){
            for (int j = 0;j<3;j  ){
                printf("aa = %d, ", retrieveArray[i][j]);
            }
            printf("n");
        }*/
    }

    if (rank != 0){
        if (notOrderedFlag == 0){
            int tmpArray[3] = {rank, notOrderedFlag, ((myFields->numberArray)[(row   tmpNmb1) - 1])};
     
            MPI_Send(tmpArray, 3, MPI_INT,  0, 1000, MPI_COMM_WORLD); //Right Array
        }
    }

    if (rank == 0){
        for ( int row1 = 0; row1 < size; row1   )
            if (retrieveArray[row1][1] == 1){
                printf("From Proccess %d - Position %d. The Array is not Ordered!n", retrieveArray[row1][0], retrieveArray[row1][2]);
            
                MPI_Abort(MPI_COMM_WORLD, 0);
            }
            else if (retrieveArray[row1][1] == 0){
                finalArray[retrieveArray[row1][0]] = retrieveArray[row1][2];
            }
        //for (int i = 0 ; i < size; i   ) printf("finalArray[%d] = %dn", i, finalArray[i]);
    }

    if ((tmpNmb2 != 0) amp;amp; (rank == 0)){
    for (int i = ((myFields->hostNumber) - tmpNmb2); i < ((myFields->hostNumber) - 1); i  ){
           if (((myFields->numberArray)[i]) > ((myFields->numberArray)[i 1])){
                printf("From Proccess 0 - Position %d. The Array is not Ordered!n", i);
      
                MPI_Abort(MPI_COMM_WORLD, 0);
            }
        }
        finalArray[nbFinalArray - 1] = myFields->numberArray[myFields->hostNumber - 1];
        for (int i = 0 ; i < size; i   ) printf("finalArray[%d] = %dn", i, finalArray[i]);
    }

    if (rank == 0){
        for (int i = 0 ; i < (nbFinalArray -1); i  ){
            if (finalArray[i] > finalArray[i 1]){
                printf("Final Array is NOT ORDRED. From Proccess 0 - Position %dn", i);
         
                MPI_Abort(MPI_COMM_WORLD, 0);
            }      
        }
    
        printf("The Array is Ordered!!!n");
    }

    MPI_Finalize();
    return 0;
}

struct fields *start(int rank, int size){
  int input;
  struct fields *myFields;
   printf("1) Type 1 For Executionn");
   printf("2) Type 2 For Exitn");
   printf("Give your choice:");     
   scanf("%d",amp;input);
   switch(input){
       case 1:
           myFields = gatherData(rank, size);
           break;
       case 2:
       default:
          //free(myFields);
          MPI_Abort(MPI_COMM_WORLD, 0);
}

//for (int i = 0 ; i < myFields->hostNumber ; i  ) printf("%dn",((myFields->numberArray)[i]));
  return myFields;
}

struct fields *gatherData(int rank, int size){
  int host;
  struct fields *myFields;

  myFields = (struct fields *)malloc(sizeof(struct fields));
  if (myFields == NULL){
    printf("Error while alloction memory for myFields struct!!!n");
 
    MPI_Abort(MPI_COMM_WORLD, 0);
 }
    
 if (rank == 0){         
    printf("Give the host of the number to be checked if they are ordered:");
    scanf("%d",amp;host);
 }

 int *nmbArray = (int *)malloc(sizeof(nmbArray) * host);    

 for (int i = 0; i < host; i  ){
    printf("Give the %d number:", i);
    scanf("%d", (amp;(nmbArray[i])));
 }  

 myFields->hostNumber = host;
 myFields->numberArray = amp;nmbArray[0];

 //for (int i = 0 ; i < host ; i  ) printf("%dn",((myFields->numberArray)[i]));
 return myFields;
  
}
  

Теперь мне приходится повторно вызывать программу снова при каждом выходе. Поэтому я пытаюсь использовать MPI_Comm_Spawn. Но я не смог найти реализацию в Интернете и перешел по этой ссылке:
https://www.mcs.anl.gov/research/projects/mpi/mpi-standard/mpi-report-2.0/node98.htm

Таким образом, mycode становится как (проект Exercise1):

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

struct fields{
  int universeSize;
  int hostNumber;
  int *numberArray;
}; 

struct fields *start(int, int, int *, int);
struct fields *gatherData(int, int, int *, int);

int main(int argc, char** argv) {
    int rank, size, universe_size, 
            *universe_sizep, flag;
    char worker_program[200] = {'/','h','o','m','e','/','k','o','n','s','t','a','n','t','i','n','o','s',
                                'd','m','s','/','N','e','t','B','e','a','n','s','P','r','o','j','e','c','t','s',
                                '/','E','x','e','r','c','i','s','e','1','_','1','/','m','a','i','n'};
    struct fields *myFields;
    setbuf(stdout, NULL);
    
    MPI_Init(amp;argc, amp;argv);
    MPI_Comm_rank(MPI_COMM_WORLD, amp;rank);
    MPI_Comm_size(MPI_COMM_WORLD, amp;size);
    MPI_Comm everyone; /* intercommunicator */ 
    //MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, amp;universe_sizep, amp;flag);
   
  //  while(1){
        system("clear");
        if (rank == 0){
            if (size != 1){
                printf("Error Manager Process should be only one!!!n");
                MPI_Abort(MPI_COMM_WORLD, 0);
            }                
            myFields = start(rank, size, universe_sizep, flag);
            //for (int i = 0 ; i < myFields->hostNumber ; i  ) printf("%dn",((myFields->numberArray)[i]));
                           
            if ((myFields->hostNumber) < ((myFields->universeSize) - 1)){
                printf("Error!!! Number of Processes is more than number of Elements.n");
                MPI_Abort(MPI_COMM_WORLD, 0); 
            }

            if (myFields->hostNumber < (2 * ((myFields->universeSize) - 1))){
                printf("Error!!! The Host of Numbers should be at least double of the number  of Processes!!!n");
                MPI_Abort(MPI_COMM_WORLD, 0); 
            }
      
            MPI_Comm_spawn(worker_program, MPI_ARGV_NULL, ((myFields->universeSize)-1), MPI_INFO_NULL, 0, 
                           MPI_COMM_SELF, amp;everyone, MPI_ERRCODES_IGNORE);
           
            
            for (int i = 1; i < ((myFields->universeSize) - 1); i  ){ 
                MPI_Send(amp;(myFields->hostNumber), 1, MPI_INT,  i, 1000, everyone); 
                MPI_Send(myFields->numberArray, myFields->hostNumber, MPI_INT, i, 1001, everyone);
            }
        }   
   // }
    MPI_Finalize();
    return 0;
}

struct fields *start(int rank,int size,int *universe_sizep,int flag){
 int input;
 struct fields *myFields;
 printf("1) Type 1 For Executionn");
 printf("2) Type 2 For Exitn");
 printf("Give your choice:");     
scanf("%d",amp;input);
switch(input){
    case 1:
        myFields = gatherData(rank, size, universe_sizep, flag);
        break;
    case 2:
    default:
        MPI_Abort(MPI_COMM_WORLD, 0);
}

//for (int i = 0 ; i < myFields->hostNumber ; i  ) printf("%dn",((myFields->numberArray)[i]));
 return myFields;
}

struct fields *gatherData(int rank,int size,int *universe_sizep,int flag){
 int host, universe_size;
 struct fields *myFields;

 myFields = (struct fields *)malloc(sizeof(struct fields));    
 if (myFields == NULL){
    printf("Cannot allocate memory for myFields structn");
    MPI_Abort(MPI_COMM_WORLD, 0);    
 }

 if (rank == 0){
    //if (!flag) { 
        printf("This MPI does not support UNIVERSE_SIZE. How manyn processes total?n"); 
        scanf("%d", amp;universe_size); 
    //} else universe_size = *universe_sizep; 

    if (universe_size == 1){
        printf("No room to start workers!!!n");
        MPI_Abort(MPI_COMM_WORLD, 0);
    } 

    printf("Give the host of the number to be checked if they are ordered:");
    scanf("%d",amp;host);

    int *nmbArray = (int *)malloc(sizeof(nmbArray) * host);    

    for (int i = 0; i < host; i  ){
        printf("Give the %d number:", i);
        scanf("%d", (amp;(nmbArray[i])));
    }  
    
    myFields->hostNumber = host;
    myFields->numberArray = amp;nmbArray[0];
    myFields->universeSize = universe_size;
 }

  //for (int i = 0 ; i < host ; i  ) printf("%dn",((myFields->numberArray)[i]));
  return myFields;      
}
  

И проект Exercise1_1:

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

struct fields{
 int hostNumber;
 int *numberArray;
};

int main(int argc, char** argv) {
    int rank, remote_size, tmpNmb1, tmpNmb2, 
            notOrderedFlag = 0, tmpI = 0,
            nbFinalArray, tmpRetrieveArray[3],
            count, row1 = 0, col1 = 0;
    struct fields *myFields;
    MPI_Status status;
    setbuf(stdout, NULL);
    
    MPI_Init(amp;argc, amp;argv);
    MPI_Comm_rank(MPI_COMM_WORLD, amp;rank);
    MPI_Comm parent; 
    MPI_Comm_get_parent(amp;parent); 
    MPI_Comm_remote_size(parent, amp;remote_size);       
    
    if (rank == 0){
        if (parent == MPI_COMM_NULL){
            printf("Error!!! while getting Parent Comuniacator.n");
            MPI_Abort(MPI_COMM_WORLD, 0);  
        }        
     
        if (remote_size != 1){
            printf("Error Manager - Parent Process should be only one!!!n");
            MPI_Abort(MPI_COMM_WORLD, 0);
        }
    }   

    if (rank == 0){
        myFields = (struct fields *)malloc(sizeof(struct fields));
        if (myFields == NULL){
            printf("Error while allocating memory for myFields structure!!!n");
            MPI_Abort(MPI_COMM_WORLD, 0);                                  
        }
        
        MPI_Recv((amp;(myFields->hostNumber)), 1, MPI_INT, 0, 1000, parent, amp;status);
        MPI_Get_count(amp;status, MPI_INT, amp;count);
        printf("Process %d received %d int(s) from Process %d with tag %d n", rank, count, status.MPI_SOURCE, status.MPI_TAG);
        printf("number = %dn", myFields->hostNumber);

        myFields->numberArray = (int *)malloc(sizeof(struct fields) * (myFields->hostNumber));
        MPI_Recv((myFields->numberArray), (myFields-> hostNumber), MPI_INT, 0, 1001, parent, amp;status);
        MPI_Get_count(amp;status, MPI_INT, amp;count);            
        //printf("Process %d received %d int(s) from Process %d with tag %d n", rank, count, status.MPI_SOURCE, status.MPI_TAG);

        /*for (int i = 0 ; i < myFields->hostNumber ; i  ){
            printf("%dn",(*(myFields->numberArray)));
            (myFields->numberArray)  ;
        }*/

        /*for (int i = 0 ; i < myFields->hostNumber ; i  ){
            printf("%dn",((myFields->numberArray)[i]));
        }*/

    //All other code are comments
    MPI_Finalize();
    return 0;
}
  

Проблема в том, что в первом случае я не могу использовать free(myFields), как показывает код, я получаю ошибку при MPI_Abort(). Освобождается ли это выделение при прерывании программы?
Во-вторых, я не могу запустить программу ни во втором случае, когда я использую MPI_spawn, ни в последнем.
Когда рабочие процессы инициализируются, имеют ли они ранг = 0 для любого указанного мной ранга?
Сообщение во втором случае отправляется от менеджера, но рабочие не отвечают. Консоль зависает.

Есть предложения?