C MPI_散射-发送二维阵列的列
我想将2D数组的列发送到单独的进程。我现在有一个完整的2d阵列,我被MPI_散射所困扰。如何将整列作为字段发送 谢谢 编辑: 我有数组-浮点a[100][101] 我已尝试通过以下方式发送阵列:C MPI_散射-发送二维阵列的列,c,mpi,C,Mpi,我想将2D数组的列发送到单独的进程。我现在有一个完整的2d阵列,我被MPI_散射所困扰。如何将整列作为字段发送 谢谢 编辑: 我有数组-浮点a[100][101] 我已尝试通过以下方式发送阵列: float send; MPI_Scatter ((void *)a, n, MPI_FLOAT,(void *)&send , 1, MPI_INT,0, MPI_COMM_WORLD); 编辑2: 我制作了新的类型_向量: MPI_Datatype newt
float send;
MPI_Scatter ((void *)a, n, MPI_FLOAT,(void *)&send , 1, MPI_INT,0, MPI_COMM_WORLD);
编辑2:
我制作了新的类型_向量:
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);
现在我正试图将它发送到我的其他进程。矩阵由浮点数填充,我的矩阵是nxn+1,因为测试是n=5,所以它是矩阵5x6。什么样的分散调用会起作用,我应该从其他进程的角度采取什么方法?我的意思是,如何获得通过分散发送的数据?分散尝试以相等的比例发送它必须发送的数据。不幸的是,C中的数据是按行存储的,而不是按列存储的。因此,您的调用将导致分散获取n个元素,然后发送每个进程m=n/(进程数)浮点 解决此问题的常用方法是创建新的MPI向量数据类型(请参阅函数MPI_Type_vector),在该数据类型中,您将能够克服C数组的行数据存储问题(因为您可以定义向量中元素之间的跨距,这正好是一行的长度)
我还没有用这种方式使用带有向量的散布,所以我不确定这是否有助于调用散布,但至少您能够轻松地按列访问数据。然后,通过使用循环将这些数据传递给相应的进程将是一种简单的方法,这有很多问题,但主要问题是内存布局。在由
a
表示的内存位置上,没有一个float
:只有float*
s指向内存中其他位置的各种float
数组。因为这些数组不一定是连续的,所以不能在它们上使用
最简单的解决方案是将矩阵存储在单个阵列中:
float a[100*101];
并按主顺序填写。然后像这样散开:
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
),并且您希望将收到的数据项的数量和类型与发送的数据项相匹配。这与此问题非常相似:。问题是,列在内存中不是连续的,所以您必须四处游荡
在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<n; i++)
array[i] = &(data[i*m]);
return array;
}
float floatfree2d(float **array) {
free(array[0]);
free(array);
return;
}
/* ... */
float **a;
nrows = 3;
ncols = 2;
a = floatalloc2d(nrows,ncols);
我会做你想做的。注意,接收进程将具有与发送进程不同的类型,因为它们存储的列数较少;因此元素之间的跨距更小
最后,你现在可以分散注意力了
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);
您的数组是如何定义的,您如何调用Scatter?谢谢您的评论,但我将使用colums进行一些计算,所以不可能有[100*101]字段。您好,请参阅我的edit2。我已经创建了新的MPI_类型_向量,但现在我很困惑,如何将正确的值传递给散点,甚至发送。。。你能帮我吗?谢谢你这么长的回复!我一定要去尝尝。与此同时,我在思考我的整个问题。我在做平行高斯消去法。因此,在开始时,我想发送到所有其他进程列,用于计算pivot。但现在我把整个矩阵发送给所有人,所以我有点希望整个矩阵会更好。。。进程将在行之间进行计数,所以我认为在所有进程上都有矩阵是有用的。
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);