【问题标题】:MPI Matrix Multiplication Using Scatter and Gather使用 Scatter 和 Gather 的 MPI 矩阵乘法
【发布时间】:2019-05-03 11:20:13
【问题描述】:

我正在尝试使用 MPI Scatter()Gather() 函数计算矩阵乘法,并且我希望能够选择矩阵大小而无需更改使用的进程数量。

我浏览了MPI Matrix Multiplication with scatter gathermatrix 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


【解决方案1】:

允许设置更大的矩阵大小,单独的数组应该是二维数组,第一维设置为基于任务/进程数的段大小:

float matrixARows[MAT_SIZE/size][MAT_SIZE];
float matrixCRows[MAT_SIZE/size][MAT_SIZE];

计数应该是:

int count = MAT_SIZE * MAT_SIZE / size;

而矩阵乘法变为:

int sum = 0;
for (int k = 0; k < MAT_SIZE/size; k++)
{
    for (int i = 0; i < MAT_SIZE; i++)
    {
        for (int j = 0; j < MAT_SIZE; j++)
        {
            sum += matARows[k][j] * matB[j][i];
        }
        matCRows[k][i] = sum;
        sum = 0;
    }
}

注意:矩阵大小必须能被任务/进程的数量整除。例如。如果使用 4 个任务,矩阵大小必须为 4、8、16、32、64、128 等...

【讨论】:

    猜你喜欢
    • 2013-12-23
    • 2018-09-08
    • 2017-10-30
    • 2011-08-23
    • 1970-01-01
    • 2012-11-04
    • 2014-04-21
    • 2015-04-03
    • 1970-01-01
    相关资源
    最近更新 更多