带有 MPI_Type_struct 的 MPI_Scatterv 子矩阵
Posted
技术标签:
【中文标题】带有 MPI_Type_struct 的 MPI_Scatterv 子矩阵【英文标题】:MPI_Scatterv submatrix with MPI_Type_struct 【发布时间】:2017-08-18 01:41:22 【问题描述】:我目前正在开发一个 MPI 程序,我正在尝试将带有 scatterv 的矩阵块发送到所有进程。
工艺说明
矩阵以数组形式给出。 首先,我使用 MPI_Type_vector 生成一个数据类型,以从原始数组中创建必要的块。 其次,我创建了一个 MPI_Type_struct,它应该包含多行块。
#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define n 16
int main(int argc, char *argv[])
MPI_Init(&argc, &argv);
MPI_Comm comm = MPI_COMM_WORLD;
int p,r;
MPI_Comm_size(comm, &p);
MPI_Comm_rank(comm, &r);
int *arr;
arr = NULL;
if (r == 0)
arr = (int *) malloc(n * n * sizeof(int));
for (int i = 0; i < n * n; i++) arr[i] = i;
for (int i = 0; i < n; i++)
printf("\n");
for (int j = 0; j < n; j++)
printf("%4d", arr[i * n + j]);
printf("\n");
int ps = sqrt(p);
int ns = n / ps;
if (r == 0)
printf("ps: %d ns: %d\n", ps, ns);
/* create datatype */
MPI_Datatype block;
MPI_Type_vector(ns, ns, n, MPI_INT, &block);
int blocks[ps];
MPI_Aint displs[ps];
for (int i = 0; i < ps; i++)
blocks[i] = 1;
displs[i] = i * sizeof(int);
MPI_Datatype types[ps];
//for (int i = 0; i < ps - 1; i++) types[i] = block;
//types[ps - 1] = MPI_UB;
types[0] = block;
for (int i = 1; i < ps; i++) types[i] = MPI_UB;
//types[0] = block;
//types[1] = MPI_UB;
if (r == 0)
printf("displs:\n");
for(int i = 0; i < ps; i++) printf("%3ld", displs[i]);
printf("\n");
MPI_Datatype row;
MPI_Type_struct(ps, blocks, displs, types, &row);
MPI_Type_commit(&row);
/* prepare scatter */
int sdispl[p]; int sendcounts[p];
for (int i = 0; i < p; i++)
sdispl[i] = (i % ps) + (i / ps) * (ns * ps);
sendcounts[i] = 1;
if (r == 0)
printf("sdispl: \n");
for (int i = 0; i < 4; i++) printf("%3d", sdispl[i]);
printf("\n");
int rcv[ns * ns];
MPI_Scatterv(arr, sendcounts, sdispl, row, rcv, ns * ns, MPI_INT, 0, comm);
int result = 1;
if (r == result)
printf("result for %d:\n", result);
for (int i = 0; i < ns * ns; i++)
printf("%4d", rcv[i]);
if ((i+1) % ns == 0) printf("\n");
if (arr != NULL) free(arr);
MPI_Finalize();
return 0;
到目前为止,块的结构是正确的。
问题
发送到进程 r = 1 的块以 3 而不是 4 开头。进程 r = 2 的块也以 6 开头,进程 r = 3 的块以 9 开头。 对于 r == 4,它会跳转到 48。
应该怎么做
开始 0 0 1 4 2 8 3 12 4 64 5 68 6 ... 15 204
我需要的帮助
我认为,我在使用 displ 和 sdispl 时犯了一些错误。
编译并运行示例
代码使用以下命令编译:
mpicc -o main main.c -lm
我运行代码:
mpirun -np 16 ./main
提前感谢您的帮助!
【问题讨论】:
您应该查看excellent answer 的相关问题。不确定你真正想用你的结构类型实现什么,我认为你把事情复杂化了。尽量避免在代码中留下各种//注释掉的语句。 谢谢你!我会根据您的提示尝试解决我的问题。 【参考方案1】:有了祖蓝的提示,我能够解决我的问题。
以下代码基于对subarrays 的出色回答。
#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define n 8
void print_arr(int *arr, int x)
printf("\n");
for (int i = 0; i < x*x; i++)
if (i % x == 0) printf("\n");
printf("%4d", arr[i]);
printf("\n");
int main(int argc, char *argv[])
MPI_Init(&argc, &argv);
MPI_Comm comm = MPI_COMM_WORLD;
int p, r;
MPI_Comm_size(comm, &p);
MPI_Comm_rank(comm, &r);
/* number of proceses in dim x and dim y */
int ps = sqrt(p);
/* number of elements in dim x and dim y in sarr */
int ns = n/ps;
/* array of data - distributed by process 0 */
int *arr = NULL;
if (r==0)
arr = (int *) malloc(n * n * sizeof(int));
for (int i = 0; i < n*n; i++) arr[i] = i;
print_arr(arr, n);
MPI_Datatype type, resizedtype;
int sizes[2] = n,n;
int subsizes[2] = ns,ns;
int starts[2] = 0,0;
MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &type);
MPI_Type_create_resized(type, 0, ns*sizeof(int), &resizedtype);
MPI_Type_commit(&resizedtype);
int counts[p];
for (int i = 0; i < p; i++) counts[i] = 1;
int displs[p];
for (int i = 0; i < p; i++) displs[i] = i%ps + i/ps * ns * ps;
/* subarray to store distributed data */
int sarr[ns * ns];
/* send submatrices to all processes */
MPI_Scatterv(arr, counts, displs, resizedtype, sarr, ns*ns, MPI_INT, 0, comm);
/* print received data for process pr */
int pr = 3;
if (r == pr)
print_arr(sarr, ns);
/* free arr */
if (arr != NULL) free(arr);
MPI_Finalize();
return 0;
你可以编译这个例子
mpicc -o main main.c
并运行它
mpirun -np 4 ./main
【讨论】:
以上是关于带有 MPI_Type_struct 的 MPI_Scatterv 子矩阵的主要内容,如果未能解决你的问题,请参考以下文章