使用 ScatterV 将数组拆分为多个进程
Using ScatterV to split an array to multiple processes
我正在使用 MPI,我必须将数组的一部分发送到不同的进程。例如,考虑 3 个进程。然后我需要将红色元素发送到第一个进程,贪婪发送到第二个进程,黑色发送到第三个进程。
我知道我可以使用 Scatterv 两次,但我想尽量减少进程之间的通信,而我要拆分的实际数组很大。有人对我如何做到这一点有建议吗?
这是我对派生数据类型的尝试:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void print_array(int *array,int n){
int i;
printf("\t[");
for (i=0; i<n; i++) {
printf(" %d",array[i]);
}
printf("]\n");
}
int main(int argc, char **argv){
int rank,world_size,i,n = 16, block_count = 2;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int *array = malloc(n * sizeof(int));
for (i=0; i<n; i++) { array[i]=i;}
if (rank==0) { print_array(array,n);}
int *sendcounts = malloc(world_size * sizeof(int));
int *reccounts = malloc(world_size * sizeof(int));
int *displs = malloc(world_size * sizeof(int));
sendcounts[0]=3; sendcounts[1]=3; sendcounts[2]=2;
displs[0]=0; displs[1]=3; displs[2]=6;
for (i=0; i<world_size; i++) {
reccounts[i] = sendcounts[i]*block_count;
}
int root = 0;
int *recvbuf = malloc(reccounts[rank] * sizeof(int));
MPI_Datatype newtype;
MPI_Type_contiguous(block_count, MPI_INT, &newtype);
MPI_Type_commit(&newtype);
if (rank==0) {
MPI_Scatterv(array, sendcounts, displs,
newtype, recvbuf, sendcounts[rank],
newtype, root, MPI_COMM_WORLD);
}
else {
MPI_Scatterv(NULL, sendcounts, displs,
newtype, recvbuf, reccounts[rank],
newtype, root, MPI_COMM_WORLD);
}
MPI_Type_free (&newtype);
print_array(recvbuf,reccounts[rank]);
free(array);array = NULL;
free(sendcounts);sendcounts = NULL;
free(displs);displs = NULL;
free(recvbuf);recvbuf = NULL;
MPI_Finalize();
return 0;
}
有办法,就是有点绕
我们的想法是创建一个派生数据类型,其中两个元素的偏移量为 0
和 8
,然后调整此数据类型的大小,使上限为一个元素的大小。
然后你可以用 counts={3,3,2}
和 displs={0,3,6}
一次 MPI_Scatterv()
。
请注意,您还需要在接收端创建派生数据类型,否则 MPI 任务 1 将在我猜您期望 {3, 4, 5, 11, 12, 13}
时收到 {3, 11, 4, 12, 5, 13}
我正在使用 MPI,我必须将数组的一部分发送到不同的进程。例如,考虑 3 个进程。然后我需要将红色元素发送到第一个进程,贪婪发送到第二个进程,黑色发送到第三个进程。
我知道我可以使用 Scatterv 两次,但我想尽量减少进程之间的通信,而我要拆分的实际数组很大。有人对我如何做到这一点有建议吗?
这是我对派生数据类型的尝试:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void print_array(int *array,int n){
int i;
printf("\t[");
for (i=0; i<n; i++) {
printf(" %d",array[i]);
}
printf("]\n");
}
int main(int argc, char **argv){
int rank,world_size,i,n = 16, block_count = 2;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int *array = malloc(n * sizeof(int));
for (i=0; i<n; i++) { array[i]=i;}
if (rank==0) { print_array(array,n);}
int *sendcounts = malloc(world_size * sizeof(int));
int *reccounts = malloc(world_size * sizeof(int));
int *displs = malloc(world_size * sizeof(int));
sendcounts[0]=3; sendcounts[1]=3; sendcounts[2]=2;
displs[0]=0; displs[1]=3; displs[2]=6;
for (i=0; i<world_size; i++) {
reccounts[i] = sendcounts[i]*block_count;
}
int root = 0;
int *recvbuf = malloc(reccounts[rank] * sizeof(int));
MPI_Datatype newtype;
MPI_Type_contiguous(block_count, MPI_INT, &newtype);
MPI_Type_commit(&newtype);
if (rank==0) {
MPI_Scatterv(array, sendcounts, displs,
newtype, recvbuf, sendcounts[rank],
newtype, root, MPI_COMM_WORLD);
}
else {
MPI_Scatterv(NULL, sendcounts, displs,
newtype, recvbuf, reccounts[rank],
newtype, root, MPI_COMM_WORLD);
}
MPI_Type_free (&newtype);
print_array(recvbuf,reccounts[rank]);
free(array);array = NULL;
free(sendcounts);sendcounts = NULL;
free(displs);displs = NULL;
free(recvbuf);recvbuf = NULL;
MPI_Finalize();
return 0;
}
有办法,就是有点绕
我们的想法是创建一个派生数据类型,其中两个元素的偏移量为 0
和 8
,然后调整此数据类型的大小,使上限为一个元素的大小。
然后你可以用 counts={3,3,2}
和 displs={0,3,6}
一次 MPI_Scatterv()
。
请注意,您还需要在接收端创建派生数据类型,否则 MPI 任务 1 将在我猜您期望 {3, 4, 5, 11, 12, 13}
{3, 11, 4, 12, 5, 13}