MPI_Scatter – 发送2D数组的列

我想发送2D数组的列,每个列都是单独的进程。 我现在有一个完整的2darrays,我被MPI_Scatter困住了。 如何将整列作为字段发送?

谢谢

编辑:

我有arrays – 浮动[100] [101]

我试图通过以下方式发送数组:

float send; MPI_Scatter ((void *)a, n, MPI_FLOAT,(void *)&send , 1, MPI_INT,0, MPI_COMM_WORLD); 

EDIT2:

我创建了新的type_vector:

  MPI_Datatype newtype; MPI_Type_vector(n, /* # column elements */ 1, /* 1 column only */ n+1, /* skip n+1 elements */ MPI_FLOAT, /* elements are float */ &newtype); /* MPI derived datatype */ MPI_Type_commit(&newtype); 

现在我试图将它发送到我的其他进程。 矩阵由浮点数填充,我的矩阵是nx n + 1,因为测试是n = 5,所以它是矩阵5 x 6. Scatter的调用是什么,我应该从其他进程的方面采取什么方法? 我的意思是,如何获取由分散发送的数据?

这与此问题非常类似: 如何从处理器MPI_Gatherv列,其中每个进程可以发送不同数量的列 。 问题是列在内存中不连续,所以你必须玩。

与C中的情况一样,缺少真正的多维数组,您必须对内存布局有点小心。 我相信 C就是这样一个静态声明的数组

 float a[nrows][ncols] 

在记忆中是连续的,所以你现在应该没事。 但是,请注意,一旦进入动态分配,就不再是这种情况; 你必须一次分配所有数据,以确保你获得连续的数据,例如

 float **floatalloc2d(int n, int m) { float *data = (float *)malloc(n*m*sizeof(float)); float **array = (float **)calloc(n*sizeof(float *)); for (int i=0; i 

但我觉得你现在还好。

既然你有这样或那样的二维数组,你必须创建你的类型。 如果您只发送一列,您所描述的类型就可以了; 但这里的诀窍是,如果你发送多个列,每列只会在前一个列的开头之后启动一个浮点数,即使列本身几乎跨越整个数组! 所以你需要移动类型的上限才能工作:

  MPI_Datatype col, coltype; MPI_Type_vector(nrows, 1, ncols, MPI_FLOAT, &col); MPI_Type_commit(&col); MPI_Type_create_resized(col, 0, 1*sizeof(float), &coltype); MPI_Type_commit(&coltype); 

会做你想做的。 请注意, 接收进程的类型与发送进程的类型不同,因为它们存储的列数较少; 因此元素之间的步幅较小。

最后,您现在可以进行分散,

 MPI_Comm_size(MPI_COMM_WORLD,&size); MPI_Comm_rank(MPI_COMM_WORLD,&rank); if (rank == 0) { a = floatalloc2d(nrows,ncols); sendptr = &(a[0][0]); } else { sendptr = NULL; } int ncolsperproc = ncols/size; /* we're assuming this divides evenly */ b = floatalloc(nrows, ncolsperproc); MPI_Datatype acol, acoltype, bcol, bcoltype; if (rank == 0) { MPI_Type_vector(nrows, 1, ncols, MPI_FLOAT, &acol); MPI_Type_commit(&acol); MPI_Type_create_resized(acol, 0, 1*sizeof(float), &acoltype); } MPI_Type_vector(nrows, 1, ncolsperproc, MPI_FLOAT, &bcol); MPI_Type_commit(&bcol); MPI_Type_create_resized(bcol, 0, 1*sizeof(float), &bcoltype); MPI_Type_commit(&bcoltype); MPI_Scatter (sendptr, ncolsperproc, acoltype, &(b[0][0]), ncolsperproc, bcoltype, 0, MPI_COMM_WORLD); 

这有很多问题,但你的主要问题是内存布局。 在由a表示的内存位置,没有一个float :只有float* s指向内存中其他地方的各种float数组。 由于这些数组不一定是连续的,因此不能对它们使用Scatter 。

最简单的解决方案是将矩阵存储在一个数组中:

 float a[100*101]; 

并按列主要顺序填写。 然后简单地像Scatter一样:

 MPI_Scatter(a, 100*101, MPI_FLOAT, send, 10*101, MPI_FLOAT, 0, MPI_COMM_WORLD); 

这假设您在10个进程之间进行分散,并且send在每个进程中被定义为float[10*101] 。 请注意,在您发布的代码中,Scatter的参数4-6肯定存在缺陷。 如果send是一个数组,那么你不需要传递&send (出于同样的原因,你不需要在第一个参数中传递&a ),并且你想要将你收到的数据项的数量和类型与你发送。

好吧,Scatter尝试以相同的比例发送它必须发送的数据。 不幸的是,C中的数据是按行存储的,而不是按列存储的。 因此,您的调用将导致Scatter获取n个元素,然后发送每个进程m = n /(进程数)浮点数。

这个问题的一个常见方法是创建一个新的MPI-vector数据类型(参见函数MPI_Type_vector),您可以在其中克服C数组的行数据存储问题(因为您可以定义元素之间的步幅)向量,这将是一行的长度)。

我没有以这种方式使用向量散布,所以我不确定这是否有助于Scatter的调用,但至少你能够轻松地按列访问数据。 然后,通过使用循环将这些数据传递给相应的过程将是一种简单的方法