0

Добрый вечер,
Я пытаюсь исправить проблему с этим кодом MPI.Как отправлять и получать граничные данные 1D массива с 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. Как я могу отладить эту программу?

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

+0

Добро пожаловать в переполнение стека! Эта часть кода выглядит ужасно. Попробуйте перевести его на минимальный примерный код, который все еще воспроизводит ошибку, иначе ваш вопрос будет отклонен и/или закрыт. На _prima vista_ я вижу следующую ошибку: '{{if (left! = NONE);' Точка с запятой в конце строки эффективно приводит к тому, что следующий блок выполняется всегда, а не только при выполнении условия. Кроме того, передача '& Q' в' MPI_Send' и 'MPI_Recv' неверна, поскольку' Q' является указателем и должен передаваться напрямую. Пожалуйста, используйте отладчик, чтобы найти остальные проблемы. –

+0

Доброе утро, Христо и спасибо за советы! Я разместил более короткую и более простую версию кода, я исправил ошибки, о которых вы сообщали, и он по-прежнему падает. К сожалению, я использую MPI на университетских серверах с Putty, и я действительно не знаю, как отлаживать его. Можете ли вы дать мне совет? Большое спасибо! – Janis90

+0

Спросите у администратора или администратора сервера, какие отладчики у них есть. Вы должны указать, какой компилятор (и его версия) вы используете. В последних версиях GCC есть санитарные ситуации, изучите https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html. Вы можете установить компилятор C и MPI на свой рабочий стол и попробовать там. –

ответ

0

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

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);} 

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

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