2015-05-08 2 views
1
#include <mpi.h> 
#include <stdlib.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    int myid, numprocs, number_of_completed_operation; 

    char message = 'a'; 


    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &myid); 

    MPI_Request* requests = (MPI_Request*)malloc((numprocs - 1)*sizeof(MPI_Request)); 
    MPI_Status* statuses = (MPI_Status*)malloc(sizeof(MPI_Status)*(numprocs - 1)); 
    int* indices = (int *)malloc((numprocs - 1)*sizeof(int)); 
    char* buf = (char *)malloc((numprocs - 1)*sizeof(char)); 

    if (myid != numprocs - 1) 
    {//worker 

     printf("***this is sender %d\n", myid); 
     MPI_Send(&message, 1, MPI_CHAR, numprocs - 1, 110, MPI_COMM_WORLD); 
     printf("*.*sender %d is done\n", myid); 



    } 
    else if (myid == numprocs - 1) 
    { 
     //master 
     int number_of_left_messages = numprocs - 1;//有numprocs-1个信息到来 
     int i; 
     for (i = 0; i < numprocs - 1; i++) 
     { 
      MPI_Irecv(&buf+i, 1, MPI_CHAR,i, 110, MPI_COMM_WORLD, &requests[i]); 
     } 

     MPI_Waitsome(numprocs - 1, requests, &number_of_completed_operation, indices, statuses); 


     number_of_left_messages = number_of_left_messages - number_of_completed_operation; 
     printf("number of completed operation is %d\n", number_of_left_messages); 
     printf("left message amount is %d\n", number_of_left_messages); 

     int j; 
     for (j = 0; j <numprocs - 1; j++) 
     { 
      printf("-------------\n"); 
      printf("index is %d\n",indices[j]); 
      printf("source is %d\n", statuses[j].MPI_SOURCE); 
      //printf("good\n"); 
      printf("--------====\n"); 

     } 

     while (number_of_left_messages > 0) 
     { 
      MPI_Waitsome(numprocs - 1, requests, &number_of_completed_operation, indices, statuses); 

      printf("number of completed operation is %d\n", number_of_completed_operation); 
      for (j = 0; j <numprocs - 1; j++) 
      { 
       printf("-------------\n"); 
       printf("index is %d\n", indices[j]); 
       printf("source is %d\n", statuses[j].MPI_SOURCE); 
       printf("--------====\n"); 
      } 
      number_of_left_messages = number_of_left_messages - number_of_completed_operation; 
      printf("left message amount is %d\n", number_of_left_messages); 

Логика проста, я установил конечный процесс как главный процесс, а весь другой процесс - рабочий процесс, рабочие отправляют сообщение хозяину, мастер использует ожидаемую функцию для Получать. Когда я устанавливаю число процессов, как 4 или больше, система показала мне ошибку следующим образом:Произошла ошибка в MPI_Waitsome

[soit-mpi-pro-1:12197] *** An error occurred in MPI_Waitsome 
[soit-mpi-pro-1:12197] *** reported by process [140533176729601,140531329925123] 
[soit-mpi-pro-1:12197] *** on communicator MPI_COMM_WORLD 
[soit-mpi-pro-1:12197] *** MPI_ERR_REQUEST: invalid request 
[soit-mpi-pro-1:12197] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort, 
[soit-mpi-pro-1:12197] *** and potentially your MPI job) 

ответ

2

Похоже, ваш призыв к MPI_Irecv может быть проблемой. Удалите лишние & до buf (у вас есть указатель на указатель вместо указателя).

MPI_Irecv(buf+i, 1, MPI_CHAR,i, 110, MPI_COMM_WORLD, &requests[i]); 

Когда я исправить, добавить закрывающие фигурные скобки и вызов MPI_Finalize(), и удалить кучу дополнительных выхода, у меня нет никаких проблем, выполнение вашей программы:

$ mpiexec -n 8 ./a.out 
***this is sender 3 
*.*sender 3 is done 
***this is sender 4 
*.*sender 4 is done 
***this is sender 5 
*.*sender 5 is done 
***this is sender 6 
*.*sender 6 is done 
***this is sender 0 
*.*sender 0 is done 
***this is sender 1 
*.*sender 1 is done 
***this is sender 2 
*.*sender 2 is done 
number of completed operation is 1 
left message amount is 6 
number of completed operation is 1 
left message amount is 5 
number of completed operation is 1 
left message amount is 4 
number of completed operation is 1 
left message amount is 3 
number of completed operation is 1 
left message amount is 2 
number of completed operation is 1 
left message amount is 1 
number of completed operation is 1 
left message amount is 0 

у меня нет идея, если она получит правильный ответ или нет, но это другой вопрос.

1

Вы отправляете MPI_Irecv адрес указателя buf сам по себе плюс смещение вместо его значения. Когда сообщение получено, оно перезаписывает последний байт (в маленьких системах, таких как x86/x64) значения одной или нескольких соседних переменных стека, которые в зависимости от компоновки стека могут включать requests и statuses. Поэтому MPI_Waitsome получает указатель, который не указывает на начало массива запросов, а скорее где-то перед ним, после него или в середине его, поэтому некоторые из дескрипторов запроса недействительны и MPI_Waitsome жалуется. В системе с большим энтиантом это приведет к перегрузке наивысшего байта адреса и, скорее, приведет к неправильному адресу и ошибке сегментации.

Либо используйте buf+i (в соответствии с ответом Уэсли Блэна), либо используйте &buf[i]. Обычно я считаю, что это вопрос личного вкуса, если использовать первую из второй формы.

Смежные вопросы