【发布时间】:2019-05-03 11:20:13
【问题描述】:
我正在尝试使用 MPI Scatter() 和 Gather() 函数计算矩阵乘法,并且我希望能够选择矩阵大小而无需更改使用的进程数量。
我浏览了MPI Matrix Multiplication with scatter gather 和matrix multiplication using Mpi_Scatter and Mpi_Gather 的帖子,但它们都使用了在定义更大的矩阵大小时不起作用的方法,但只有当矩阵大小与进程/节点相同时大小。
我的代码示例矩阵大小为 8:
#define MAT_SIZE 8
void initialiseMatricies(float a[][MAT_SIZE], float b[][MAT_SIZE], float c[][MAT_SIZE])
{
int num = 11;
for (int i = 0; i < MAT_SIZE; i++)
{
for (int j = 0; j < MAT_SIZE; j++)
{
a[i][j] = num;
b[i][j] = num+1;
c[i][j] = 0;
}
num++;
}
}
int main(int argc, char **argv)
{
// MPI Variables
int rank, size;
// Create the main matrices with the predefined size
float matrixA[MAT_SIZE][MAT_SIZE];
float matrixB[MAT_SIZE][MAT_SIZE];
float matrixC[MAT_SIZE][MAT_SIZE];
// Create the separate arrays for storing the scattered rows from the main matrices
float matrixARows[MAT_SIZE];
float matrixCRows[MAT_SIZE];
// Initialise the matrices
initialiseMatricies(matrixA, matrixB, matrixC);
// Start the MPI parallel sequence
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int count = MAT_SIZE * MAT_SIZE / (size * (MAT_SIZE / size));
// Scatter rows of first matrix to different processes
MPI_Scatter(matrixA, count, MPI_INT, matrixARows, count, MPI_INT, 0, MPI_COMM_WORLD);
// Broadcast second matrix to all processes
MPI_Bcast(matrixB, MAT_SIZE * MAT_SIZE, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
// Matrix Multiplication
int sum = 0;
for (int i = 0; i < MAT_SIZE; i++)
{
for (int j = 0; j < MAT_SIZE; j++)
{
sum += matARows[j] * matB[j][i];
}
matCRows[i] = sum;
}
// Gather the row sums from the buffer and put it in matrix C
MPI_Gather(matrixCRows, count, MPI_INT, matrixC, count, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
// if it's on the master node
if (rank == 0)
printResults(matrixA, matrixB, matrixC, calcTime);
return 0;
}
输出:
1364 2728 4092 5456 6820 8184 9548 10912
1488 2976 4464 5952 7440 8928 10416 11904
1612 3224 4836 6448 8060 9672 11284 12896
1736 3472 5208 6944 8680 10416 12152 13888
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
输出是正确的,如果我将进程数设置为 8(与矩阵大小相同),则正确计算整个矩阵,但我不想这样做。我相信我的问题源于Scatter() 和Gather() 内部的计数。如果我将计数设置为:
int count = MAT_SIZE * MAT_SIZE / size;
那么输出变成:
1364 2728 4092 5456 6820 8184 9548 10912
-1.07374e+08 -1.07374e+08 11 11 11 11 11 11
1612 3224 4836 6448 8060 9672 11284 12896
-1.07374e+08 -1.07374e+08 13 13 13 13 13 13
1860 3720 5580 7440 9300 11160 13020 14880
-1.07374e+08 -1.07374e+08 15 15 15 15 15 15
2108 4216 6324 8432 10540 12648 14756 16864
-1.07374e+08 -1.07374e+08 17 17 17 17 17 17
因为计数基本上从 8(之前的)变为 16,并且每个进程都给了我一个调试错误说
“运行时检查失败 #2 - 变量 'matrixC' 周围的堆栈已损坏”
我已经改变这个计数公式几天了,但仍然无法弄清楚。我试过改变我的矩阵乘法开始和结束迭代,但也无法弄清楚。
【问题讨论】:
-
你想分散什么?每个 MPI 任务一行(在这种情况下,如果行数多于任务,您必须重申)?
MAT_SIZE/size每个任务行数?在这种情况下,您必须assert(0 == MAT_SIZE%size)、count = MAT_SIZE * MAT_SIZE / size和(至少)float matrixARows[MAT_SIZE/size][MAT_SIZE]; -
@GillesGouaillardet 是的,我试图为每个任务执行
MAT_SIZE/size行。我按照您所说的将matrixARows 和matrixCRows 都设为2D 数组,并添加了一个额外的for() 循环来将矩阵相乘,并且效果很好!非常感谢。我是 MPI 的新手,您为我节省了很多时间。
标签: c++ mpi matrix-multiplication scatter