Матрица MPI с использованием Scatter и Gather - PullRequest
0 голосов
/ 03 мая 2019

Я пытаюсь вычислить матричное умножение, используя функции MPI Scatter() и Gather(), и я хочу иметь возможность выбирать размер матрицы без необходимости изменять количество используемых процессов.

Я просмотрел сообщения MPI Matrix Multiplication с умножением разброса и матричного умножения с использованием Mpi_Scatter и 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' поврежден"

Я изменил эту формулу подсчета в течение пары дней и до сих пор не могу понять это. Я попытался изменить начало и конец итерации умножения матриц, но не могу понять и это.

1 Ответ

0 голосов
/ 04 мая 2019

Допускается установка большего размера матрицы, отдельные массивы должны быть двумерными массивами с 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 и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...