C 如何使用并行计算机(MPI)乘法矩阵

C 如何使用并行计算机(MPI)乘法矩阵,c,parallel-processing,mpi,C,Parallel Processing,Mpi,我正在努力让我的代码使用MPI运行。我正在尝试实现矩阵乘法 我的代码是这样的 有两个矩阵A和B 把一行一行地分散开来 广播矩阵B 计算 聚集 我已经写了代码…但是代码运行不正常。。。我犯了一个错误 我不知道为什么会发生这种情况…我尝试了很多次调整代码…但似乎总是有什么地方出错 有人能检查一下这个代码并告诉我为什么代码不起作用吗 我补充说: “散射矩阵” “收集答案”等等……所以,即使你能浏览一下这个节目的分散部分,告诉我为什么不对,我也会心存感激 #define N 512 #include &

我正在努力让我的代码使用MPI运行。我正在尝试实现矩阵乘法

我的代码是这样的

  • 有两个矩阵A和B

  • 把一行一行地分散开来

  • 广播矩阵B

  • 计算

  • 聚集

  • 我已经写了代码…但是代码运行不正常。。。我犯了一个错误

    我不知道为什么会发生这种情况…我尝试了很多次调整代码…但似乎总是有什么地方出错

    有人能检查一下这个代码并告诉我为什么代码不起作用吗

    我补充说:

    “散射矩阵”

    “收集答案”等等……所以,即使你能浏览一下这个节目的分散部分,告诉我为什么不对,我也会心存感激

    #define N 512
    #include <stdio.h>
    #include <math.h>
    #include <sys/time.h>
    #include "mpi.h"
    void print_results(char *prompt, float result[N][N]);
    int main(int argc, char *argv[])
    {
    int i, j, k;
    MPI_Status status;
    int process_rank;//rank of a process
    int no_of_processes;//no. of processes
    
    int Master_To_Slave = 0;
    int Slave_To_Master = 5;
    
    float a[N][N], b[N][N], c[N][N];
    char *usage = "Usage: %s file\n";
    FILE *fd;
    double elapsed_time, start_time, end_time;
    struct timeval tv1, tv2;
    if (argc < 2) {
    fprintf (stderr, usage, argv[0]);
    return -1;
    }
    if ((fd = fopen (argv[1], "r")) == NULL) {
    fprintf (stderr, "%s: Cannot open file %s for reading.\n",
    argv[0], argv[1]);
    fprintf (stderr, usage, argv[0]);
    return -1;
    }
    // Read input from file for matrices a and b.
    // The I/O is not timed because this I/O needs
    // to be done regardless of whether this program
    // is run sequentially on one processor or in
    // parallel on many processors. Therefore, it is
    // irrelevant when considering speedup.
    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
            {
                fscanf (fd, "%f", &a[i][j]);
    
            }
    }
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            fscanf (fd, "%f", &b[i][j]);
    
    int num_of_rows_A = N;
    int num_of_cols_A = N;
    
    int num_of_rows_B = N;
    int num_of_cols_B = N;
    
    int lower_index_of_A;
    int upper_index_of_A;
    
    //TODO: Add a barrier prior to the time stamp.
    MPI_Init(&argc, &argv); //initialize MPI operations
    MPI_Barrier(MPI_COMM_WORLD); //Added Barrier
    
    
    // Take a time stamp
    gettimeofday(&tv1, NULL);
    
    //TODO: Scatter the input matrices a and b.
    
    
        MPI_Comm_rank(MPI_COMM_WORLD, &process_rank); //get the rank
        MPI_Comm_size(MPI_COMM_WORLD, &no_of_processes); //get number of processes
    
        if(process_rank==0){
            fprintf (stderr, "Main process started");
            fprintf (stderr, "No. of process %d",no_of_processes);
            fprintf (stderr, "\n\n");
            fprintf (stderr, "\n\n");
    
        for( i=1; i<no_of_processes;i++)
        {
            int rows_per_process = num_of_rows_A/(no_of_processes-1);
    
             lower_index_of_A = (i-1)*rows_per_process;
           // fprintf (stderr, "Current lower Index of A %s",lower_index_of_A);
    
            if(i+1==no_of_processes &&((num_of_rows_A%(no_of_processes-1))!=0))
            {
                upper_index_of_A=num_of_rows_A; 
               // fprintf (stderr, "Current upper Index of A %s",upper_index_of_A);
            }
            else
            {         
                upper_index_of_A=lower_index_of_A+rows_per_process;
               // fprintf (stderr, "Current upper Index of A %s",upper_index_of_A);
            }
            fprintf (stderr, "Lower index of A %d", lower_index_of_A);
            fprintf (stderr, "Upper index of A %d", upper_index_of_A);
            fprintf (stderr, "\n\n");
    
            MPI_Send(&lower_index_of_A,1,MPI_INT,i,Master_To_Slave,MPI_COMM_WORLD); //send lower index
            MPI_Send(&upper_index_of_A,1,MPI_INT,i,Master_To_Slave+1,MPI_COMM_WORLD);//send upper  index
    
            MPI_Send(&a[lower_index_of_A][0],(upper_index_of_A-lower_index_of_A)*num_of_cols_A,MPI_DOUBLE,i,Master_To_Slave+2,MPI_COMM_WORLD);//send rows of A
            fprintf (stderr, "Scatter done");
    
        }
        MPI_Bcast(&b, num_of_rows_A*num_of_cols_B, MPI_DOUBLE, 0, MPI_COMM_WORLD);
        fprintf (stderr, "Broadcast done");
        }
        else
        {
    
    
            MPI_Recv(&lower_index_of_A, 1, MPI_INT, 0, Master_To_Slave,MPI_COMM_WORLD, &status);
    
            MPI_Recv(&upper_index_of_A, 1, MPI_INT, 0, Master_To_Slave+1,MPI_COMM_WORLD,&status);
    
            MPI_Recv(&a[lower_index_of_A], (upper_index_of_A-lower_index_of_A)*num_of_cols_A, MPI_DOUBLE,0, Master_To_Slave+2,MPI_COMM_WORLD, &status);
    
            //TODO: Add code to implement matrix multiplication (C=AxB) in parallel.
    
    
            for( i=lower_index_of_A;i<upper_index_of_A;i++)
            {
                for( j=0;j<num_of_cols_B;j++)
                {
                    for( k=0;k<num_of_rows_B;k++)
                    {
    
                        c[i][j]+=(a[i][k]*b[k][j]);
    
                    }
                }
            }
    
            MPI_Send(&lower_index_of_A, 1, MPI_INT, 0, Slave_To_Master,MPI_COMM_WORLD);
            MPI_Send(&upper_index_of_A, 1, MPI_INT, 0, Slave_To_Master+1,MPI_COMM_WORLD);
            MPI_Send(&c[lower_index_of_A], (upper_index_of_A-lower_index_of_A)*num_of_cols_B, MPI_DOUBLE,0, Slave_To_Master+2,MPI_COMM_WORLD);
        }
    
    
    
    
    //TODO: Gather partial result back to the master process.
        if(process_rank==0)
        {   
            for(i=1;i<no_of_processes;i++)
            {
    
                MPI_Recv(&lower_index_of_A, 1, MPI_INT, i, Slave_To_Master, MPI_COMM_WORLD, &status);
                //receive upper bound from a slave
                MPI_Recv(&upper_index_of_A, 1, MPI_INT, i, Slave_To_Master + 1, MPI_COMM_WORLD, &status);
                //receive processed data from a slave
                MPI_Recv(&c[lower_index_of_A][0], (upper_index_of_A - lower_index_of_A) * num_of_cols_B, MPI_DOUBLE, i, Slave_To_Master + 2, MPI_COMM_WORLD, &status);
            }
    
        }
    
    
    
    
    // Take a time stamp. This won't happen until after the master
    // process has gathered all the input from the other processes.
    gettimeofday(&tv2, NULL);
    elapsed_time = (tv2.tv_sec - tv1.tv_sec) +
    ((tv2.tv_usec - tv1.tv_usec) / 1000000.0);
    printf ("elapsed_time=\t%lf (seconds)\n", elapsed_time);
    // print results
    print_results("C = ", c);
    }
    void print_results(char *prompt, float result[N][N])
    {
    int i, j;
    printf ("\n\n%s\n", prompt);
    for (i = 0; i < N; i++) {
    for (j = 0; j < N; j++) {
    printf(" %.2f", result[i][j]);
    }
    printf ("\n");
    }
    printf ("\n\n");
    }
    
    #定义N 512
    #包括
    #包括
    #包括
    #包括“mpi.h”
    作废打印结果(字符*提示,浮点结果[N][N]);
    int main(int argc,char*argv[])
    {
    int i,j,k;
    MPI_状态;
    int进程\u秩;//进程的秩
    int no_of_进程;//进程数
    int Master_到_Slave=0;
    int-Slave-To-Master=5;
    浮动a[N][N]、b[N][N]、c[N][N];
    char*usage=“用法:%s文件\n”;
    文件*fd;
    双倍运行时间、开始时间、结束时间;
    结构时间值tv1,tv2;
    如果(argc<2){
    fprintf(标准,用法,argv[0]);
    返回-1;
    }
    如果((fd=fopen(argv[1],“r”)==NULL){
    fprintf(stderr,“%s:无法打开文件%s进行读取。\n”,
    argv[0],argv[1]);
    fprintf(标准,用法,argv[0]);
    返回-1;
    }
    //从文件中读取矩阵a和b的输入。
    //I/O未计时,因为此I/O需要
    //无论此程序是否
    //在一个处理器上或在中顺序运行
    //在许多处理器上并行。因此
    //考虑加速时不相关。
    对于(i=0;i对于(i=1;i每当发生这种情况时,我都会启动一个调试器

    我总是推荐并行调试器,但我有偏见,因为我是开发它的团队之一,但它有助于发现此类错误。您也可以尝试GDB,但这将需要更多的手动干预来处理多个进程

    在您的例子中,您发布的代码在my MPI(Open MPI)中没有分段错误,它实际上挂起在进程0中的MPI_Bcast,其余挂起在其循环分支中的MPI_发送。这是因为排名1和更高级别的代码没有调用MPI_Bcast:它们需要匹配发送方,排名0,然后接收数据


    为什么不下载一个调试器,自己看看呢?一旦你修复了这个广播不匹配问题,调试器会在你找到正在查找的分段错误后立即停止你的程序,并告诉你错误所在。

    每当发生这种情况时,我就会启动一个调试器

    我总是推荐并行调试器,但我有偏见,因为我是开发它的团队之一,但它有助于发现此类错误。您也可以尝试GDB,但这将需要更多的手动干预来处理多个进程

    在您的例子中,您发布的代码在my MPI(Open MPI)中没有分段错误,它实际上挂起在进程0中的MPI_Bcast,其余挂起在其循环分支中的MPI_发送。这是因为排名1和更高级别的代码没有调用MPI_Bcast:它们需要匹配发送方,排名0,然后接收数据


    为什么不下载一个调试器并亲自查看-一旦您修复了此广播不匹配,调试器将在您找到正在查找的分段错误后立即停止您的程序,并显示错误所在。

    使用MPI函数
    MPI\u Scatter
    MPI\u Gather
    ,您可能会更成功这个问题正在成为一个常见问题,下面是另一个相关的问答——您可能会更成功地使用MPI函数
    MPI_Scatter
    MPI_Gather
    。这个问题正在成为一个常见问题,所以,这里是另一个相关的问答--