如何在MPI中发送具有每个处理器变体的2D阵列

时间:2015-11-18 06:32:38

标签: c arrays parallel-processing mpi

我正在尝试在根0上采用随机生成的数组,稍微随机地改变它,并将每个变体发送到另一个处理器。到目前为止,这是我的代码:

#include "stdio.h"
#include "stdlib.h"
#include "mpi.h"
#include "math.h"

int main(int argc, char **argv) {

  int N = 32;
  int dim = 3;
  float a = 10.0;
  int size, rank, i, j, k, q;
  float **C;
  float rijx, rijy, rijz, rij, Vij, E=0;
  float stepsize = 0.05;

  double Start_time, End_time, Elapse_time;
  MPI_Status status;

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  C = (float **)malloc(N * sizeof(float*)); // 32 particles

  for (i = 0; i < N; i++) {
    C[i]=(float *)malloc(dim*sizeof(float)); // x, y, z
  }

  MPI_Barrier(MPI_COMM_WORLD);

  if(rank == 0) {
    Start_time = MPI_Wtime();
  }

  if (rank == 0) {
  for(i = 0; i < N; i++) {
    for(j = 0; j < dim; j++) {
      C[i][j] = (float)rand()/(float)(RAND_MAX/a);
      //printf("%f\n",C[i][j]);
    }
  }
  }

// this is to generate some slight variations in the array

  float** randomsteps(float **matrix) {
for(i = 0; i < N; i = i+(rand()%(32/size))) {
   for (j = 0; j < dim; j++) {
      if(i%2 == 0) {
        C[i][j] = C[i][j]+stepsize;
          if(C[i][j] > 10) {
            C[i][j] = C[i][j] - 10;
          }
      } else {
        C[i][j] = C[i][j]-stepsize;
        if(C[i][j] < 0) {
          C[i][j] = C[i][j] + 10;
        }
      }
   }
}
return C;
  }


// and here I try to send the array
  if(rank == 0) {
   for(i=0; i<size; i++) {
    C = randomsteps(C);

    MPI_Send(&C, N*3, MPI_FLOAT, i, 10+i, MPI_COMM_WORLD);
   }
  }

  if(rank != 0) {
    for(i=0; i<size; i++) {
      MPI_Recv(&C, N*3, MPI_FLOAT, 0, 10+i, MPI_COMM_WORLD, &status);
    }
  }

MPI_Barrier(MPI_COMM_WORLD);

  MPI_Finalize();

  return 0;
}

代码的一个明显问题是随机数的生成方式有些幼稚(每次运行程序时都会给出相同的值)。这是我以后可以处理的事情。

目前,我只是想知道 - 我发送和接收阵列的方式有什么问题?在使用MPI发送和接收时,如何最好地格式化数据,我遇到了很多麻烦。我将如何修复这部分代码?

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

这里的问题是所有MPI调用都期望内存是连续的。你的记忆在给定的行中只是连续的,而你所指的2D数组实际上是一个指针数组。指针不可移植,因此尝试向另一个进程发送或广播指针数组毫无意义,而且MPI本身不支持深层复制,因此这种方法不起作用。

但是,如果将阵列分配更改为以下内容:

  float** C;
  float* C_buff;
  C = (float**)malloc(N * sizeof(float*)); // 32 particles
  C_buff = (float*)malloc(N * dim * sizeof(float)); // buffer for particles

  float* p = &C_buff[0];
  for (i = 0; i < N; i++) {
    C[i]=p;
    p+= dim*sizeof(float));
  }

[免责声明:用浏览器编写,完全未经测试,自担风险使用]

这样C_buff表示2D数组的连续内存,而C包含C_buff连续分配中内存的行指针,然后您可以使用现有代码进行初始化,但是然后做这样的事情:

MPI_Send(&C_buff[0][0], N*DIM, MPI_FLOAT, i, 10+i, MPI_COMM_WORLD);

即。使用C_buff进行MPI调用,它应该可以正常工作。