我正在使用MPI_Scatter和MPI_Gather实现矩阵乘法。如果进程数均匀分为矩阵行数列,我的代码可以正常工作。但是,当它们没有均匀分配时,它会在MPI_Gather上崩溃。这是有道理的,因为MPI_Gather期望从每个进程获得一定数量,并且不会从最后一个进程获得那么多。有没有办法让这项工作?我查看了MPI_Gatherv,但我不希望数据之间有空格 - 我只是希望它收到的数量少于上一个进程的数量。
目前,我正在使用MPI_Scatter向每个进程发送以下数量:
ceil(N/size)
其中size是我正在使用的进程数,N是矩阵中的行数和列数。最后一个进程将不会收到与其他进程一样多的数据。当我到达最后一个进程中的数据末尾时,我确保停止进行乘法运算。如果无法更改我的MPI_Gather调用,我可以更改此分散+乘法部分。任何帮助表示赞赏。
答案 0 :(得分:0)
答案 1 :(得分:0)
我认为在辅助函数中包装MPI_Scatterv
和MPI_Gatherv
是可行的方法。今天我写了一对这样的包装作为我暑期学校的一部分,如果你还需要解决方案,请随意使用它们。
void fillCounts(int rank, int size, int totalCount, int *counts, int *offsets) {
int i;
int n;
int sum;
n = totalCount / size;
for (i = 0; i < size; i++)
counts[i] = n;
for (i = 0; i < totalCount % size; i++)
counts[i] += 1;
sum = 0;
for (i = 0; i < size; i++) {
offsets[i] = sum;
sum += counts[i];
}
}
int scatter01(const void *sendBuf, int totalCount, MPI_Datatype dataType,
void *recvBuf, int *recvCount,
int root, MPI_Comm comm) {
int rank;
int size;
int *counts;
int *offsets;
MPI_Comm_rank(comm, &rank);
MPI_Comm_size(comm, &size);
counts = alloca(size * sizeof(int));
offsets = alloca(size * sizeof(int));
fillCounts(rank, size, totalCount, counts, offsets);
*recvCount = counts[rank];
return MPI_Scatterv(sendBuf, counts, offsets, dataType,
recvBuf, counts[rank, dataType, root, comm);
}
int gather01(void *recvBuf, int totalCount, MPI_Datatype dataType,
const void *sendBuf, int root, MPI_Comm comm) {
int rank;
int size;
int *counts;
int *offsets;
MPI_Comm_rank(comm, &rank);
MPI_Comm_size(comm, &size);
counts = alloca(size * sizeof(int));
offsets = alloca(size * sizeof(int));
fillCounts(rank, size, totalCount, counts, offsets);
return MPI_Gatherv(sendBuf, counts[rank], dataType,
recvBuf, counts, offsets, dataType, root, comm);
}
用法示例:
double globData[N];
double partData[N/size+1];
int n;
scatter01(globData, N, MPI_DOUBLE, partData, &n, 0, MPI_COMM_WORLD);
gather01 (globData, N, MPI_DOUBLE, partData, 0, MPI_COMM_WORLD);
答案 2 :(得分:0)
MPI_Gather
用于从各个进程收集相同大小的信息。如果要收集的数组大小因进程而异,则应使用MPI_GatherV
。