如何在 MPI 中发送每个处理器都有变化的二维数组
How to send a 2D array in MPI with variation for each processor
我试图在根 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 发送和接收时,我在思考如何最好地格式化数据时遇到了很多麻烦。我将如何修复这部分代码?
在此先感谢您的帮助!
这里的问题是所有 MPI 调用都期望内存是连续的。您的内存仅在给定行内是连续的,您所指的二维数组实际上是一个指针数组。指针是不可移植的,所以试图向另一个进程发送或广播指针数组是没有意义的,而且 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
代表二维数组的连续内存,并且 C
包含指向 C_buff
连续分配内存中的行指针,那么您可以使用现有代码初始化,然后做这样的事情:
MPI_Send(&C_buff[0][0], N*DIM, MPI_FLOAT, i, 10+i, MPI_COMM_WORLD);
即。使用 C_buff
进行 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 发送和接收时,我在思考如何最好地格式化数据时遇到了很多麻烦。我将如何修复这部分代码?
在此先感谢您的帮助!
这里的问题是所有 MPI 调用都期望内存是连续的。您的内存仅在给定行内是连续的,您所指的二维数组实际上是一个指针数组。指针是不可移植的,所以试图向另一个进程发送或广播指针数组是没有意义的,而且 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
代表二维数组的连续内存,并且 C
包含指向 C_buff
连续分配内存中的行指针,那么您可以使用现有代码初始化,然后做这样的事情:
MPI_Send(&C_buff[0][0], N*DIM, MPI_FLOAT, i, 10+i, MPI_COMM_WORLD);
即。使用 C_buff
进行 MPI 调用,它应该可以工作。