【问题标题】:How to send and receive boundary data of an 1D array with MPI?如何使用 MPI 发送和接收一维数组的边界数据?
【发布时间】:2015-02-11 11:27:33
【问题描述】:

晚上好,
我正在尝试解决此 MPI 代码的问题。

Master 可以将 1D 数组块发送给 slave,但是当 worker 与邻居交换数据时程序崩溃。我可以争辩说这是因为我应该创建一个向量数据类型来只发送最后一个元素到右边和第一个元素向左。我该怎么做?

这是给我带来问题的代码部分:

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 的大学服务器。如何调试这个程序?

非常感谢,希望有人能帮助我!

【问题讨论】:

  • 欢迎来到 Stack Overflow!这么多代码看起来很糟糕。请尝试将其提炼为仍然重现错误的最小示例代码,否则您的问题将被否决和/或关闭。在 prima vista 上,我发现了以下错误:{{if (left != NONE); 行尾的分号有效地导致始终执行以下块,而不仅仅是在满足条件时执行。此外,将&amp;Q 传递给MPI_SendMPI_Recv 是错误的,因为Q 本身就是指针,应该直接传递。请使用调试器查找其余问题。
  • 早上好 Hristo,谢谢你的建议!我发布了一个更短更简单的代码版本,我修复了你报告的错误,但它仍然崩溃。不幸的是,我正在使用 Putty 在大学服务器上使用 MPI,我真的不知道如何调试它。你能给我一个建议吗?非常感谢!
  • 询问服务器的支持或管理员他们有哪些调试器。您必须指定您使用的编译器(及其版本)。最新版本的 GCC 进行了清理,请研究 gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html 。您可以在桌面上安装 C 编译器和 MPI 并在那里尝试。

标签: pointers parallel-processing segmentation-fault mpi distributed-computing


【解决方案1】:

我尝试使用非阻塞,现在它可以工作了。程序崩溃是因为任务没有以正确的方式接收和发送数据。我也改变了数据的大小,这是我没有看到的另一个错误。而不是

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

谢谢大家的帮助!

【讨论】:

    猜你喜欢
    • 2011-08-19
    • 2018-11-11
    • 2012-10-18
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    相关资源
    最近更新 更多