2015-09-20 2 views
1

Я узнал о программировании MPI и наткнулся на следующий stackoverflow question. Я использую этот самый «ответный» пример, чтобы вычислить сумму каждой строки таким образом, чтобы она увеличивала перекрытие. Это массив 2 на 3, и я хочу рассчитать сумму, как только эти элементы массива достигнут MPI_Irecv. Я редактировал свой код между MPI_Irecv и MPI_Wait, чтобы начать вычислять, как только элементы массива станут доступными. Но когда я запускаю код, мне кажется, что я неправильно звонил MPI_Test. Если вы можете решить это с помощью примера, я бы очень признателен.MPI Overlapping с использованием языка C для создания суммирования массива

Использование mpirun -np 3 test 0-й ранг будет генерировать элементы массива. 1 и 2 рангов рассчитают сумму

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

int main (int argc, char *argv[]) 
{ 
     MPI_Init(&argc, &argv); 
     int world_rank; 
     MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); 
     int world_size; 
     MPI_Comm_size(MPI_COMM_WORLD, &world_size);   
     int tag = 1;   
     int arr[2][3]; 
     MPI_Request request; 
     MPI_Status status; 
     int source = 0; 
     int dest; 
     int flag; 

     printf ("\n--Current Rank: %d\n", world_rank); 
     //To handle the number of process received by the user will be handled here later 
     if (world_rank == 0) 
     { 
      int i = 1; 
      int a, b, x, y; 

      printf("* Rank 0 excecuting\n"); 
      for(x=0; x<2; x++)//Generating the whole 2 by 3 2D array 
      { 
       i++; 
       for (y = 0; y < 3; y++) 
       { 
        arr[x][y] = i;//first row contain all 2 
       }     //second row contain all 3 
      } 

      int subarray_index; 
      for(subarray_index=0; subarray_index < 2; subarray_index++) 
      { 
       dest = subarray_index%(world_size - 1) + 1;  
       tag = subarray_index; 
       MPI_Isend(&arr[subarray_index][0], 3, MPI_INT, dest, tag, MPI_COMM_WORLD, &request); 
      } 
     } 
     else 
     { 
      int a, b;     
      for(b=0; b<2/(world_size-1); b++) 
      { 
       int sum = 0; 
       int i;     
       int my_offset = world_rank-1; 
       tag = b*(world_size-1) + my_offset; 
       int subarray = b; 
       MPI_Irecv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &request); 
       MPI_Test(&request, &flag, &status);//I think there may be an error at MPI_Test too 
       while (flag != 1) 
       { 
        MPI_Test(&request, &flag, &status); 
        for(i = 0; i<3; i++) 
        { 
         //if(!arr[subarray][i])//want to wait till I recive actual array elements 
         //{//This need to start calculating as soon as array element become avilable 
          printf("%d) arr[subarray][i]:%d at rank %d\n", tag, arr[subarray][i], world_rank); 
          sum = arr[subarray][i]+sum; 
         //} 
        } 
       }     
       printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, tag); 
       MPI_Wait (&request, &status); 
      }   
     } 
     MPI_Finalize(); 
} 

Когда я набираю в mpirun -np 3 test Ответе должен быть «Сумма в 6» и «Сумма составляет 9»

--Current Rank: 2 
1) arr[subarray][i]:40896 at rank 2 
1) arr[subarray][i]:32767 at rank 2 
1) arr[subarray][i]:617513272 at rank 2 
1) arr[subarray][i]:40896 at rank 2 
1) arr[subarray][i]:32767 at rank 2 
1) arr[subarray][i]:617513272 at rank 2 
1) arr[subarray][i]:40896 at rank 2 
1) arr[subarray][i]:32767 at rank 2 
1) arr[subarray][i]:617513272 at rank 2 //all above arr element shows it's empty 
1) arr[subarray][i]:3 at rank 2 //following three values are correct and these 
1) arr[subarray][i]:3 at rank 2 //are the only three that need to use for summing 
1) arr[subarray][i]:3 at rank 2 

Sum is: 1909043312 at rank: 2 and tag is:1 

--Current Rank: 0 
* Rank 0 excecuting 

--Current Rank: 1 //here I don't get arr element values as above 

Sum is: 0 at rank: 1 and tag is:0 

ответ

2

Не уверен, что ваш вопрос. Но из вашего описания я бы вывел, что процесс 1 достигает MPI_Test, когда сообщение уже получено. Таким образом, flag уже установлен, и цикл никогда не вводится.

С другой стороны, с рангом 2 вы добавляете неинициализированные значения из-за безусловного выполнения суммирования во время ожидания сообщения, которое должно быть получено.

Вы можете сделать суммирование только после получения сообщения. То есть, когда флаг установлен, который после цикла в то время и в основном аннулирует всю конструкцию, как вы могли бы просто сделать:

MPI_Irecv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &request); 
MPI_Wait (&request, &status); 

Ожидание вернется, как только сообщение становится доступным, который является точка MPI_Wait. Теперь приведенное выше в основном эквивалентно блокировке MPI_Recv.

С другой стороны, вы должны подождать, пока сообщение не закончится в какой-то момент на стороне отправки. Там вам понадобятся индивидуальные запросы для каждого MPI_Isend. Затем вы можете использовать MPI_Waitall после вашего цикла отправки.

Таким образом, вы, возможно, хотели что-то вроде этого (с блокировкой приема):

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

int main (int argc, char *argv[]) 
{ 
     MPI_Init(&argc, &argv); 
     int world_rank; 
     MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); 
     int world_size; 
     MPI_Comm_size(MPI_COMM_WORLD, &world_size); 
     int tag = 1; 
     int arr[2][3]; 
     MPI_Request request[2]; 
     int source = 0; 
     int dest; 
     int flag; 

     printf ("\n--Current Rank: %d\n", world_rank); 
     //To handle the number of process received by the user will be handled here later 
     if (world_rank == 0) 
     { 
      int i = 1; 
      int a, b, x, y; 
      MPI_Status status[2]; 

      printf("* Rank 0 excecuting\n"); 
      for(x=0; x<2; x++)//Generating the whole 2 by 3 2D array 
      { 
       i++; 
       for (y = 0; y < 3; y++) 
       { 
        arr[x][y] = i;//first row contain all 2 
       }     //second row contain all 3 
       dest = x%(world_size - 1) + 1; 
       tag = x; 
       MPI_Isend(&arr[x][0], 3, MPI_INT, dest, tag, MPI_COMM_WORLD, &request[x]); 
      } 

      MPI_Waitall(2, &request[0], &status[0]); 

     } 
     else 
     { 
      int a, b; 
      MPI_Status status; 

      for(b=0; b<2/(world_size-1); b++) 
      { 
       int sum = 0; 
       int i; 
       int my_offset = world_rank-1; 
       tag = b*(world_size-1) + my_offset; 
       int subarray = b; 
       MPI_Recv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &status); 
       for(i = 0; i<3; i++) 
       { 
        //if(!arr[subarray][i])//want to wait till I recive actual array elements 
        //{//This need to start calculating as soon as array element become avilable 
         printf("%d) arr[subarray][i]:%d at rank %d\n", tag, arr[subarray][i], world_rank); 
         sum = arr[subarray][i]+sum; 
        //} 
       } 
       printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, tag); 
      } 
     } 
     MPI_Finalize(); 
} 

Это отсылает значения как можно скорее, и действует на другой стороне по рядам, как только они . Вы все равно можете отправлять несколько сообщений на принимающей стороне, если этот процесс обрабатывает несколько строк, но в этом случае вам нужно снова массив запросов, и вы должны использовать MPI_Waitany или MPI_Waitsome, чтобы как можно скорее действовать в отношении полученных сообщений ,

Вот приемная часть с MPI_Waitany:

{ 
    int a, b; 
    MPI_Status status; 
    MPI_Request request[2/(world_size-1)]; 

    for(b=0; b<2/(world_size-1); b++) 
    { 
     int my_offset = world_rank-1; 
     tag = b*(world_size-1) + my_offset; 
     int subarray = b; 
     MPI_Irecv(&arr[subarray][0], 3, MPI_INT, source, tag, MPI_COMM_WORLD, &request[b]); 
    } 
    for(b=0; b<2/(world_size-1); b++) 
    { 
     int sum = 0; 
     int i; 
     MPI_Waitany(2/(world_size-1), &request[0], &a, &status); 
     for(i = 0; i<3; i++) 
     { 
       printf("%d) arr[subarray][i]:%d at rank %d\n", status.MPI_TAG, arr[a][i], world_rank); 
       sum = arr[a][i]+sum; 
     } 
     printf("\nSum is: %d at rank: %d and tag is:%d\n", sum, world_rank, status.MPI_TAG); 
    } 
} 
+0

Спасибо большое за такой подробный ответ и объяснить все в деталях. Ты лучший –

+0

@ Learner_51 Рад, что это тебе помогло. Повеселись. – haraldkl

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