Как отправлять и получать граничные данные 1D массива с MPI?

98
6

Добрый вечер,
Я пытаюсь исправить проблему с этим кодом MPI.

Мастер может отправлять блоки 1D-массива в подчиненные устройства, но когда работники обмениваются данными с соседями, программа сбой. Я могу утверждать, что это связано с тем, что я должен создать векторный тип данных для отправки только последнего элемента вправо и первого элемента влево. Как я могу это сделать?

это часть кода, которая вызывает у меня проблемы:

numworkers = numtasks-1;
if (taskid == MASTER) {
printf("Master\n");
double *Q=malloc(m * n * cell_size * sizeof(double));
/*Set initial Gauss hump*/
for (k=0;k<3;k++)
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
Q(k,i,j) = 4.0;
}
}
printf("gauss done.\n");
averow = (m*n*cell_size)/numworkers;
extra = (m*n*cell_size)%numworkers;
MPI_Type_contiguous(rows, MPI_DOUBLE, &rowtype);!
MPI_Type_commit(&rowtype);

printf ("Starting program with %d worker tasks.\n", numworkers);
printf("Grid size: X= %d Y= %d Time steps= %d\n",m,n,STEPS);

for (i=1; i<=numworkers; i++) // Distribute work to workers.
{rows = (i <= extra) ? averow+1 : averow;
if (i == 1) // neighbors
left = NONE;
else
left = i - 1;
if (i == numworkers)
right = NONE;
else
right = i + 1;
/* Now send startup information to each worker */
dest = i;
MPI_Send(&rows, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD);
MPI_Send(&left, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD);
MPI_Send(&right, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD);
MPI_Send(Q,1, rowtype, dest, BEGIN,
MPI_COMM_WORLD);
printf("Sent to task %d: rows= %d offset= %d ",dest,rows,offset);
printf("left= %d right= %d\n",left,right);
offset = offset + rows;
}
for (i=1; i<=numworkers; i++)
{
source = i;
msgtype = DONE;
MPI_Irecv(&rows, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &request);
MPI_Irecv(Q, 1,rowtype, source,
msgtype, MPI_COMM_WORLD, &request);
}
printf("Solver took\n");
free(Q);
MPI_Type_free(&rowtype);
MPI_Finalize();}

if (taskid != MASTER)
{MPI_Recv(&rows, 1, MPI_INT, MASTER, BEGIN, MPI_COMM_WORLD, &status);
double *Q =malloc(rows* sizeof(double));
MPI_Recv(&left, 1, MPI_INT, MASTER, BEGIN, MPI_COMM_WORLD, &status);
MPI_Recv(&right, 1, MPI_INT, MASTER, BEGIN, MPI_COMM_WORLD, &status);
MPI_Recv(Q, rows, MPI_DOUBLE, MASTER, BEGIN, MPI_COMM_WORLD, &status);
printf("ricevo da master rows %d \n",rows);
printf("Task %d received work. Beginning time steps...\n",taskid);
for (it = 1; it <= numworkers; it++)
{{if (left != NONE) //boundary data exchange
{MPI_Send(Q, 1, MPI_DOUBLE, left,
RTAG, MPI_COMM_WORLD);
source = left;
msgtype = LTAG;
MPI_Recv(Q, 1, MPI_DOUBLE, source,
msgtype, MPI_COMM_WORLD, &status);}
if (right != NONE)
{
MPI_Send(Q, 1, MPI_DOUBLE, right,
LTAG, MPI_COMM_WORLD);
source = right;
msgtype = RTAG;
MPI_Recv(Q, 1, MPI_DOUBLE, source, msgtype,
MPI_COMM_WORLD, &status);}
/* Now call update to update the value of grid points*/
Q=Q+1;
printf("update fatto."); }
/* Finally, send my portion of final results back to master */
MPI_Send(&offset, 1, MPI_INT, MASTER, DONE, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, MASTER, DONE, MPI_COMM_WORLD);
MPI_Send(Q, rows, MPI_DOUBLE, MASTER, DONE,
MPI_COMM_WORLD);
free(Q);
MPI_Type_free(&rowtype);
MPI_Finalize();
}

Q определяется как:

  #define Q(i,j,k) Q[((k) + n * ((j) + m * (i)))]

Для отладки: я использую университетский сервер с Putty. Как я могу отладить эту программу?

Большое вам спасибо, надеюсь, кто-то мне поможет!

спросил(а) 2014-12-12T20:28:00+03:00 6 лет, 6 месяцев назад
1
Решение
77

Я пытался использовать Non-Blocking, и теперь он работает. Программа потерпела крах, потому что задачи не получали и отправляли данные в правильном направлении. Я также изменил размер данных, это была еще одна ошибка, которую я не видел. Вместо

if (left != NONE)  //boundary data exchange
{MPI_Send(Q, 1, MPI_DOUBLE, left,
RTAG, MPI_COMM_WORLD);
source = left;
msgtype = LTAG;
MPI_Recv(Q, 1, MPI_DOUBLE, source,
msgtype, MPI_COMM_WORLD, &status);}
if (right != NONE)
{
MPI_Send(Q, 1, MPI_DOUBLE, right,
LTAG, MPI_COMM_WORLD);
source = right;
msgtype = RTAG;
MPI_Recv(Q, 1, MPI_DOUBLE, source, msgtype,
MPI_COMM_WORLD, &status);}

Я использовал:

if (left != NONE)  //boundary data exchange
{MPI_Isend(Q, rows, MPI_DOUBLE, left,
RTAG, MPI_COMM_WORLD,&req1);
source = left;
msgtype = LTAG;
MPI_Irecv(Q, rows, MPI_DOUBLE, source,
msgtype, MPI_COMM_WORLD, &req2);
printf("boundary left done");
MPI_Wait(&req1,&status);
MPI_Wait(&req2,&status);
}

if (right != NONE)
{
MPI_Isend(Q, rows, MPI_DOUBLE, right,
LTAG, MPI_COMM_WORLD,&req3);
source = right;
msgtype = RTAG;
MPI_Irecv(Q, rows, MPI_DOUBLE, source, msgtype,
MPI_COMM_WORLD, &req4);
printf("boundary right done");
MPI_Wait(&req3,&status);
MPI_Wait(&req4,&status);}

Спасибо всем за помощь!

ответил(а) 2014-12-23T20:23:00+03:00 6 лет, 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема