MPI_Bcast通信的MPI分段错误

时间:2014-06-03 16:24:21

标签: c mpi

我有一个MPI程序,如果我使用一个节点就可以正常工作,如果我有多个通信关闭它也可以正常运行(虽然数字结果错误,因为计算需要通信)。但是,当我通过通信运行时,我得到的地址没有映射分段错误。

我已将我的程序减少到下面的基本大纲。我有一个在我的主程序之外定义的结构。然后我们有一个这些结构的数组,这个结构数组在MPI节点之间划分,例如我们可能有500个粒子和5个节点,所以第一个节点在0-99上运行,依此类推。但是,在每次操作之后,所有节点都需要同步它们的数据,我尝试用MPI_Bcast实现这一点。

在MPI节点之间的通信中使用全局结构是否有问题?或者为什么这种通信结构会给出分段错误。

#define BUFFER 2

typedef struct {
    double X[BUFFER];
} Particle;

Particle *body;

void Communication(int i_buf, int size){

  // there are N particles which have been operated on by the various MPI nodes
  // we seek to synchronize this data between all nodes
  #pragma omp parallel for
  for(int nbody = 0; nbody < N; nbody++)
  {
    // below returns the node number which operated on this particle  
    int node = IsNode(nbody, size);

    MPI_Bcast(&(body[nbody].X[i_buf]), 1, MPI_DOUBLE, node, MPI_COMM_WORLD);
  }

}

void main() {

MPI_Init(&argc, &argv);

int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);

body = (Particle*) calloc((size_t)N, sizeof(Particle));

  int adjust_a, adjust_b, a, b;
  adjust_a = Min(rank, N % size);
  adjust_b = Min(rank + 1, N % size);
  a = N / size * rank + adjust_a;
  b = N / size * (rank + 1) + adjust_b;


  int i_buf, i_buf_old;

  for(int i_time = 0; i_time <= time_steps; i_time++)
  {

    i_buf = Mod(i_time, BUFFER);
    i_buf_old = Mod(i_time - 1, BUFFER);

    #pragma omp sections
    {
      #pragma omp section
      {
        Compute(i_buf, i_buf_old, a, b); // just does some calc
        Communication(i_buf, size);
      }
      #pragma omp section
      {
      if((i_time != 0) && (rank == 0))
        LogThread(i_buf_old); // just writes to a file
      }
    }

  }

我的完整结构是:

typedef struct {
    double mass;
    double X[BUFFER];
    double Y[BUFFER];
    double Z[BUFFER];
    double Vx[BUFFER];
    double Vy[BUFFER];
    double Vz[BUFFER];
    double Fx[BUFFER];
    double Fy[BUFFER];
    double Fz[BUFFER];
} Particle;

1 个答案:

答案 0 :(得分:1)

听起来你可能正在使用错误的工具来完成工作。如果您尝试聚合来自所有进程的数据数组并确保所有进程都具有该聚合的结果,那么您可能应该使用MPI_ALLGATHER

此功能可以满足您的需求。如果您处于每个进程都有一些数据(例如整数)的情况,请执行以下操作:

0)    0
1)    1
2)    2
3)    3

当您进行allgather时,结果将是:

0) 0 1 2 3
1) 0 1 2 3
2) 0 1 2 3
3) 0 1 2 3

例如,如果您只需要在一个地方聚合数据(例如排名0),那么您可以使用MPI_GATHER,如下所示:

0) 0 1 2 3
1)    1
2)    2
3)    3