MPI发送Recv。在运行时打印出错误的进程和分段错误等级

时间:2012-04-29 13:53:29

标签: segmentation-fault mpi

void iso_diffusion_denoising(image *u, image *u_bar, float kappa, int iters) { 

  int my_rank,num_procs;
  float *temp;
  int i,j,k=0;
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
  MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
  int m=u->m;
  int n=u->n;
  //temp= malloc(n*sizeof(float));//1*n array ?

  float *ptr;

  for(k=0;k<iters;k++) {

for(i=1; i<m-1; i++) { 

  for(j=1; j<n-1; j++) {

    /*  temp[m-1]=u->image_data[m-1][0];
    temp[m-1]=u->image_data[m-1][n-1];
    temp[i]=u->image_data[m-1][j];*/


    u_bar->image_data[i][j]= u->image_data[i][j] + kappa*(u->image_data[i-1][j] + u->image_data[i][j-1] - 4*u->image_data[i][j] + u->image_data[i][j+1] + u->image_data[i+1][j]);
    u->image_data[i][j]=u_bar->image_data[i][j];
  } 
}

//temp[m-1][n-1]
if(my_rank==0) {
  ptr = u->image_data[m-1];
  MPI_Send(&ptr[0],n,MPI_FLOAT,1,1,MPI_COMM_WORLD);
  MPI_Recv(&temp,n,MPI_FLOAT,1,2,MPI_COMM_WORLD,&status);
  printf("my rank is :  %d ", my_rank);
  fflush(stdout);
} else if(my_rank==1) { //if(my_rank!=num_procs) {
  ptr = u->image_data[0];
  MPI_Send(&ptr[0],n,MPI_FLOAT,0,2,MPI_COMM_WORLD);
  MPI_Recv(&temp,n,MPI_FLOAT,1,1,MPI_COMM_WORLD,&status);
  printf("my rank is :  %d ", my_rank);
  fflush(stdout);
}

  }

}

mpirun -np 2 Oblig 0.1 20 noisy denoised

my rank is : 1114636288 [safir:22140] *** Process received signal ***
--------------------------------------------------------------------------
mpirun noticed that process rank 0 with PID 22140 on node safir.ifi.uio.no exited on signal 11 (Segmentation fault).

为什么my_rank打印出一个非常大的值?我也遇到了分段错误。

2 个答案:

答案 0 :(得分:3)

问题似乎是您对MPI_Recv的第一个参数。在这里,您发送一个指向temp的指针,它本身就是一个指针。 MPI_Recv正在尝试从为n指针保留的内存位置开始复制temp个浮点数。您需要为temp分配内存(取消对malloc的调用)并将MPI_Recv调用更改为:

MPI_Recv(temp, ...

这很可能是my_rank获得垃圾价值的地方。 MPI_Recv正在尝试写入存储n * sizeof(float)的{​​{1}}字节数据,并覆盖到为其他变量保留的内存中,即temp

并且忘记释放为my_rank完成后为temp分配的内存!

还有其他一些事情,我做了很少的MPI编程,但我认为my_rank == 1块中的MPI_Recv调用应该有0的源。我还认为MPI_Send和MPI_Recv阻塞了调用 - 在换句话说,他们不会返回,直到转移完成或失败。由于你的两个队伍都首先调用MPI_Send,我希望它们能够阻止你的程序并使其死锁。也许他们失败了 - 你应该检查MPI_Send的返回值是否成功。

答案 1 :(得分:0)

除了segfaulting,你的代码也可能会阻塞,因为对于较大的n你的MPI实现可能会使用同步语义和死锁,因为两个排队等待MPI_Send完成以便发布接收但是永远不会发生因为要返回同步发送,必须发布匹配的接收。

您应该在其中一个MPI_Send个案例中交换MPI_Recvif的顺序(例如my_rank == 0)或者(更好的解决方案)是使用专门设计为永不死锁的MPI_Sendrecv

回答你为什么排名被打印的问题 - 堆栈损坏。通过传递缓冲区指针的地址,您实际上会在堆栈中接收消息,从而覆盖其他局部变量。