矩阵乘法,使用MPI实现Cannon算法

时间:2015-08-31 09:34:50

标签: process mpi

首先,当然我看到了类似的问题和解决方案,但我的实现有点不同。 主要问题是,我的代码只适用于一个进程,但它不适用于更多进程。 我不知道这是什么原因......可能是流程之间的沟通,但我无法弄明白; /

#include <mpi.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
    int x = 0;
    double kk;
    int proces;
    int numprocs;
    int right_neigh, left_neigh, up_neigh, down_neigh;
    int tag = 99;

    static const int n = 6; //size of matrices

    int psa[n][n]; //nxn
    int psb[n][n];
    int pra[n][n];
    int prb[n][n];
    int c[n][n];

    for (int i = 0; i < n; i++) { //let's make fist matrix
        for (int j = 0; j < n; j++) {
            psa[i][j] = (int)rand() % 100 + 1;
            psb[i][j] = (int)rand() % 100 + 1;
            c[i][j] = 0;
        }
    }

    for (int i = 0; i < n; i++) { //an the 2nd one
        for (int j = 0; j < n; j++) {
            pra[i][j] = psa[i][j];
            prb[i][j] = psb[i][j];

        }
    }
    MPI_Status statRecv[2];
    MPI_Request reqSend[2], reqRecv[2];

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &proces);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);


    int PP = numprocs;
    double np = numprocs;
    kk = sqrt(np);
    int k = (int)kk;
    if (proces < k) // below neighbour set
    {
        left_neigh = (proces + k - 1) % k;
        right_neigh = (proces + k + 1) % k;
        up_neigh = ((k - 1)*k) + proces;
    }
    if (proces == k)
    {
        left_neigh = ((proces + k - 1) % k) + k;
        right_neigh = ((proces + k + 1) % k) + k;
        up_neigh = proces - k;
    }
    if (proces > k)
    {
        x = proces / k;
        left_neigh = ((proces + k - 1) % k) + x * k;
        right_neigh = ((proces + k + 1) % k) + x * k;
        up_neigh = proces - k;
    }
    if (proces == 0 || (proces / k) < (k - 1))
    {
        down_neigh = proces + k;
    }
    if ((proces / k) == (k - 1))
    {
        down_neigh = proces - ((k - 1)*k);
    }
    x = 0;

    for(int kk = 0; kk < PP; kk++) //algorithm
    {
        for (int i = 0; i < n / PP; i++)
        {
            for (int j = 0; j < n / PP; j++)
            {
                for (int k = 0; k < n / PP; k++)
                {
                    c[i][j] += psa[i][k] * psb[k][j];
                }
            }
        }
        MPI_Irecv(pra, n*n / PP / PP,MPI_FLOAT,left_neigh, tag,MPI_COMM_WORLD, reqRecv);
        MPI_Irecv(prb, n*n / PP / PP,MPI_FLOAT,down_neigh,tag,MPI_COMM_WORLD,&reqRecv[1]);
        MPI_Isend(psa, n*n / PP / PP,MPI_FLOAT,right_neigh,tag,MPI_COMM_WORLD, reqSend);
        MPI_Isend(psb, n*n / PP / PP,MPI_FLOAT,up_neigh,tag,MPI_COMM_WORLD,&reqSend[1]);
        MPI_Wait(reqRecv, statRecv);

    }

    cout << "A" << endl; //show result
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << pra[i][j] << " ";
        }
        cout << endl;
    }
    cout << "B" << endl;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << prb[i][j] << " ";
        }
        cout << endl;
    }
    cout << "C" << endl;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << c[i][j] << " ";
        }
        cout << endl;
    }


    MPI_Finalize();

    return 0;
}

1 个答案:

答案 0 :(得分:1)

好的,我做到了。现在一切都很酷,我的朋友帮助了我。但管理员请不要删除它,它可能对某人有帮助。

#include <mpi.h>
#include <stdio.h>
#include <math.h>
#include <iostream> using namespace std; int main(int argc, char **argv) {  int x = 0;  double kk;  int proces;     int numprocs;   int prawy_sasiad, lewy_sasiad, gorny_sasiad, dolny_sasiad;  int tag = 99;

static const int n = 4; //rozmiar tablic
const int PP = 2; // pierwiastek z liczby procesow
int A[n][n] = {}, B[n][n] = {};
for (int i = 0; i < n; i++) {//inicjalizacja macierzy glownych
for (int j = 0; j < n; j++) {
A[i][j] = (int)rand() % 100 + 1;
B[i][j] = (int)rand() % 100 + 1;
}
}

/*
int val = 1;
for (int i = 0; i < n; i++) { //inicjalizacja macierzy glownych
    for (int j = 0; j < n; j++) {
        A[i][j] = val;
        B[i][j] = val;
        val++;
    }
}
*/
MPI_Status  statRecv2;
MPI_Request reqSend2, reqRecv2;
MPI_Status  statRecv[2];
MPI_Request reqSend[2], reqRecv[2];
MPI_Init(0, 0);
MPI_Comm_rank(MPI_COMM_WORLD, &proces);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
int pra[n / PP][n / PP] = {}, psa[n / PP][n / PP] = {};// podmacierze
int prb[n / PP][n / PP] = {}, psb[n / PP][n / PP] = {};
//int C[n / PP][n / PP] = {};//wynikowa
int C[n][n] = {};//wynikowa
//cout << proces << endl;
for (int i = 0; i < n / PP; i++)//podzielenie macierzy glownej na podmacierze, kazdy proces otrzymuje inna podmacierz
{
    for (int j = 0; j < n / PP; j++)
    {
        psa[i][j] = A[proces / PP*(n / PP) + i][proces%PP*(n / PP) + j];
        psb[i][j] = B[proces / PP*(n / PP) + i][proces%PP*(n / PP) + j];
        //cout << A[proces / PP*(n / PP) + i][proces%PP*(n / PP) + j] << " ";
    }
    //cout << endl;
}

double np = numprocs;
kk = sqrt(np);
int k = (int)kk;


if (proces < k) // ustawienie sasiadow
{
    lewy_sasiad = (proces + k - 1) % k;
    prawy_sasiad = (proces + k + 1) % k;
    gorny_sasiad = ((k - 1)*k) + proces;
}
if (proces == k)
{
    lewy_sasiad = ((proces + k - 1) % k) + k;
    prawy_sasiad = ((proces + k + 1) % k) + k;
    gorny_sasiad = proces - k;
}
if (proces > k)
{
    x = proces / k;
    lewy_sasiad = ((proces + k - 1) % k) + x * k;
    prawy_sasiad = ((proces + k + 1) % k) + x * k;
    gorny_sasiad = proces - k;
}
if (proces == 0 || (proces / k) < (k - 1))
{
    dolny_sasiad = proces + k;
}
if ((proces / k) == (k - 1))
{
    dolny_sasiad = proces - ((k - 1)*k);
}
x = 0;
int p = 0;
do{ //przesuniecia
    if (p < proces / PP)// w wierszu
    {

        MPI_Irecv(pra, n*n / PP / PP, MPI_FLOAT, prawy_sasiad, tag, MPI_COMM_WORLD, &reqRecv2);
        MPI_Isend(psa, n*n / PP / PP, MPI_FLOAT, lewy_sasiad, tag, MPI_COMM_WORLD, &reqSend2);
        MPI_Wait(&reqRecv2, &statRecv2);
        for (int i = 0; i < n / PP; i++)
        {
            for (int j = 0; j < n / PP; j++)
            {
                psa[i][j] = pra[i][j];
            }
        }
}
    MPI_Barrier(MPI_COMM_WORLD);
if (p < proces % PP)// i w kolumnie
{

    MPI_Irecv(prb, n*n / PP / PP, MPI_FLOAT, dolny_sasiad, tag, MPI_COMM_WORLD, &reqRecv2);
    MPI_Isend(psb, n*n / PP / PP, MPI_FLOAT, gorny_sasiad, tag, MPI_COMM_WORLD, &reqSend2);
    MPI_Wait(&reqRecv2, &statRecv2);
    for (int i = 0; i < n / PP; i++)
    {
        for (int j = 0; j < n / PP; j++)
        {
            psb[i][j] = prb[i][j];
        }
    }

}
MPI_Barrier(MPI_COMM_WORLD);
p++;
} while (p < n);
//MPI_Barrier(MPI_COMM_WORLD);


for (int kkk = 0; kkk < PP; kkk++) //algorytm
{
    for (int i = 0; i < n / PP; i++)
    {
        for (int j = 0; j < n / PP; j++)
        {
            for (int k = 0; k < n / PP; k++)
            {
                C[i][j] += psa[i][k] * psb[k][j];
            }
        }
    }


    MPI_Irecv(pra, n*n / PP / PP, MPI_FLOAT, prawy_sasiad, tag, MPI_COMM_WORLD, reqRecv);
    MPI_Irecv(prb, n*n / PP / PP, MPI_FLOAT, dolny_sasiad, tag, MPI_COMM_WORLD, &reqRecv[1]);
    MPI_Isend(psa, n*n / PP / PP, MPI_FLOAT, lewy_sasiad, tag, MPI_COMM_WORLD, reqSend);
    MPI_Isend(psb, n*n / PP / PP, MPI_FLOAT, gorny_sasiad, tag, MPI_COMM_WORLD, &reqSend[1]);
    MPI_Wait(reqRecv, statRecv);
    MPI_Barrier(MPI_COMM_WORLD);

    for (int i = 0; i < n / PP; i++)
    {
        for (int j = 0; j < n / PP; j++)
        {
            psa[i][j] = pra[i][j];
        }
    }


    for (int i = 0; i < n / PP; i++)
    {
        for (int j = 0; j < n / PP; j++)
        {
            psb[i][j] = prb[i][j];
        }
    }


}


cout << "Proces: " << proces << " ";
for (int i = 0; i < n / PP; i++)
{
    for (int j = 0; j < n / PP; j++)
    {
        cout << C[i][j] << " ";
    }
}

MPI_Finalize();

return 0;
}