2016-12-09 5 views
1

Я попытался сделать сумму матрицы, используя MPI, чтобы сделать это, я не знаю, почему, но я не могу отправить какие-либо данные с помощью MPI_Send, но что я пытаюсь я получаю сообщение об ошибке:C++ MPI: не удалось отправить что-либо

Sending 3 rows to task 1 offset=0 
Sending 3 rows to task 2 offset=3 
Sending 2 rows to task 3 offset=6 
Sending 2 rows to task 4 offset=8 
*** An error occurred in MPI_Send 
*** reported by process [1047527425,0] 
*** on communicator MPI_COMM_WORLD 
*** MPI_ERR_RANK: invalid rank 
*** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort, 
*** and potentially your MPI job) 

Вот мой код:

# include <mpi.h> 
# include <stdio.h> 
# include <stdlib.h> 
# include <time.h> 
# include <vector> 

#define ROWS 10 
#define COLONS 10 
#define MASTER 0 

using namespace std; 

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

    int rows; 

    int averow=0; 
    int extra=0; 
    int offset; 
    int numprocs; 
    MPI_Status status; 
    int matrixA[ROWS][COLONS]; 
    int matrixB[ROWS][COLONS]; 
    int matrixC[ROWS][COLONS]; 

    for (int i = 0; i < COLONS; i++) { 
     for (int j = 0; j < ROWS; j++) { 
      matrixA[i][j] = rand() % 10; 
      matrixB[i][j] = rand() % 10; 
     } 
    } 
    int my_id; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_id); 
    if (my_id == MASTER) { 

     averow = ROWS/numprocs; 
     extra = ROWS % numprocs; 
     offset = 0; 

     /* Send matrix data to the worker tasks */ 
     for (int dest = 1; dest <= numprocs; dest++) { 
      rows = (dest <= extra) ? averow + 1 : averow; 
      printf("Sending %d rows to task %d offset=%d\n", rows, dest, offset); 
      MPI_Send(&offset, 1, MPI_INT, dest, 1, MPI_COMM_WORLD); 
      MPI_Send(&rows, 1, MPI_INT, dest, 1, MPI_COMM_WORLD); 
      MPI_Send(&matrixA[offset][0], rows * ROWS, MPI_DOUBLE, dest, 1, 
      MPI_COMM_WORLD); 
      MPI_Send(&matrixB, COLONS * COLONS, MPI_INT, dest, 1, 
      MPI_COMM_WORLD); 
      offset = offset + rows; 
     } 

     /* Receive results from worker tasks */ 
     for (int i = 1; i <= numprocs; i++) { 
      int source = i; 
      MPI_Recv(&offset, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status); 
      MPI_Recv(&rows, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status); 
      MPI_Recv(&matrixC[offset][0], rows * COLONS, MPI_INT, source, 2, 
      MPI_COMM_WORLD, &status); 
      printf("Received results from task %d\n", source); 
     } 
    } 

    if (my_id != MASTER) { 
     MPI_Recv(&offset, 1, MPI_INT, MASTER, 1, MPI_COMM_WORLD, &status); 
     MPI_Recv(&rows, 1, MPI_INT, MASTER, 1, MPI_COMM_WORLD, &status); 
     MPI_Recv(&matrixA, rows * COLONS, MPI_DOUBLE, MASTER, 1, MPI_COMM_WORLD, &status); 
     MPI_Recv(&matrixB, COLONS * COLONS, MPI_DOUBLE, MASTER, 1, 
     MPI_COMM_WORLD, &status); 

     for (int k = 0; k < COLONS; k++) { 
      for (int i = 0; i < rows; i++) { 
       matrixC[k][i] = matrixA[k][i] + matrixB[k][i]; 
      } 
     } 
     MPI_Send(&offset, 1, MPI_INT, MASTER, 2, MPI_COMM_WORLD); 
     MPI_Send(&rows, 1, MPI_INT, MASTER, 2, MPI_COMM_WORLD); 
     MPI_Send(&matrixC, rows * COLONS, MPI_DOUBLE, MASTER, 2, 
     MPI_COMM_WORLD); 
    } 
    MPI_Finalize(); 

    return 0; 
} 

Я бег этой программы 8 процесса.

У вас есть представление, что я делаю неправильно здесь, ребята? Потому что я ничего не вижу.

+2

Почти всегда нецелесообразно помечать вопрос как C, так и C++. Это программа на C++, хотя мне кажется, что она должна быть C-программой с тривиальными изменениями, и поэтому я удалил тег C. – zwol

+2

Кстати, 'COLONS' должна быть' COLUMNS' на протяжении всей этой программы. – zwol

+0

Я подтверждаю проблему, кстати. Я редактировал то, что программа печатает _before_ сообщение об ошибке, так как это показывает, что ошибка не возникает при первом вызове 'MPI_Send'. – zwol

ответ

1

Есть несколько вещей неправильно в вашем коде:

  1. петли для dest и i должны быть < numprocs. В противном случае ваш код пытается отправить в ранг 8, которого не существует!
  2. В некоторых случаях вы используете тип данных MPI_DOUBLE, несмотря на отсутствие данных double. Отправка MPI_INT и получение MPI_DOUBLE также не работает.
  3. MPI_Send(&matrixA[offset][0], rows * ROWS, ..., должно быть rows * COLONS.
  4. MPI_Send(&matrixB, COLONS * COLONS, ..., должно быть ROWS * COLONS, также на соответствующих MPI_Recv.
  5. Передача всего matrixB при отправке кусков matrixA, также не имеет смысла в свете вычисления добавления.
  6. Первым измерением вашей матрицы является ряд, второй - coumn. Однако, ваша петля добавления смешивает это неправильно.
  7. rows и offset в ваших Получить результаты с рабочих заданий настроены неправильно.

Я не уверен, что я ловил каждые фактические ошибки, есть также некоторые аспекты, которые могут быть значительно улучшены:

  1. Имея постоянную ROWS и переменную rows с другим значением является чрезвычайно декрементным к легко понимая код.
  2. Ваша установка связи излишне сложна. Вы можете упростить шаблоны во многих местах, например. вычислите rows и offset локально вместо отправки. Но самое главное, вы должны использовать коллективные операции. Это намного проще рассуждать, а также намного лучше.
  3. В MPI главный ранг обычно участвует в вычислении.

Не обескураживайте. Для новичков может быть трудно понять MPI, и очень часто приходится создавать (неправильные и неэффективные) шаблоны, которые легко могут быть сделаны с коллективами. Моя рекомендация:

  1. Начать с нуля, отменить свою текущую попытку.
  2. Подробнее о MPI_Scatterv, а также MPI_Gatherv. Это единственные коммуникационные функции, которые вам нужны в вашем примере. Также нет необходимости в отдельных путях кода вокруг тех, которые используются для мастера.
  3. Подумайте о своем расположении данных. Какова форма матриц на каждом ранге. Как глобальная матрица отображает локальные.
  4. Используйте имена переменных, которые описывают их значение однозначно и кратко.
  5. Напишите свой код небольшими шагами и тщательно подумайте о каждой строке и параметре.
  6. Если это работает, разместите его на Code Review. Если это не работает или вы застряли, опубликуйте новый вопрос или обновите это. В обоих случаях вы можете оставить комментарий здесь.
Смежные вопросы