用MPI并行实现高斯消元法

时间:2014-08-11 05:30:07

标签: c mpi

我对MPI很新,我被要求为高斯消除编写一个C并行实现(无需旋转)。
我试了一下(我使用了行式分解),但我的代码不起作用。我希望有人能在这里给我一些指示。我已经在几天内一直在寻找错误但没有成功:(
先感谢您 !

#include<stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);

    int i,j,k;
    int map[500];
    float A[500][500],b[500],c[500],x[500],sum=0.0;
    double range=1.0;
    int n=3;
    int rank, nprocs;
    clock_t begin1, end1, begin2, end2;
    MPI_Status status;

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);   /* get current process id */
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs); /* get number of processes */

//////////////////////////////////////////////////////////////////////////////////

    if (rank==0)
    {
        for (i=0; i<n; i++)
        {
        for (j=0; j<n; j++)
        A[i][j]=range*(1.0-2.0*(double)rand()/RAND_MAX);
        b[i]=range*(1.0-2.0*(double)rand()/RAND_MAX);
        }
        printf("\n Matrix A (generated randomly):\n");
        for (i=0; i<n; i++)
        {
            for (j=0; j<n; j++)
            printf("%9.6lf ",A[i][j]);
        printf("\n");
        }
        printf("\n Vector b (generated randomly):\n");
        for (i=0; i<n; i++)
            printf("%9.6lf ",b[i]);
        printf("\n\n");
    }

//////////////////////////////////////////////////////////////////////////////////

    begin1 =clock();

    MPI_Bcast (A,n*n,MPI_DOUBLE,0,MPI_COMM_WORLD);
    MPI_Bcast (b,n,MPI_DOUBLE,0,MPI_COMM_WORLD);    

    for(i=0; i<n; i++)
    {
        map[i]= i % nprocs;
    } 

    for(k=0;k<n;k++)
    {
        MPI_Bcast (&A[k][k],n-k,MPI_DOUBLE,map[k],MPI_COMM_WORLD);
        MPI_Bcast (&b[k],1,MPI_DOUBLE,map[k],MPI_COMM_WORLD);
        for(i= k+1; i<n; i++) 
        {
            if(map[i] == rank)
            {
                c[i]=A[i][k]/A[k][k];
            }
        }               
        for(i= k+1; i<n; i++) 
        {       
            if(map[i] == rank)
            {
                for(j=0;j<n;j++)
                {
                    A[i][j]=A[i][j]-( c[i]*A[k][j] );
                }
                b[i]=b[i]-( c[i]*b[k] );
            }
        }
    }
    end1 = clock();

//////////////////////////////////////////////////////////////////////////////////

    begin2 =clock();

    if (rank==0)
    { 
    x[n-1]=b[n-1]/A[n-1][n-1];
    for(i=n-2;i>=0;i--)
    {
        sum=0;

        for(j=i+1;j<n;j++)
        {
            sum=sum+A[i][j]*x[j];
        }
        x[i]=(b[i]-sum)/A[i][i];
    }

    end2 = clock();
    }
//////////////////////////////////////////////////////////////////////////////////
    if (rank==0)
    { 
        printf("\nThe solution is:");
        for(i=0;i<n;i++)
        {
            printf("\nx%d=%f\t",i,x[i]);

        }

        printf("\n\nLU decomposition time: %f", (double)(end1 - begin1) / CLOCKS_PER_SEC);
        printf("\nBack substitution time: %f\n", (double)(end2 - begin2) / CLOCKS_PER_SEC);
    }

    return(0);

    MPI_Finalize();
}

这就是我得到的错误:
mpirun已退出,因为进程等级为1,节点XXXX上的PID XXXX退出而未调用&#34;最终确定&#34;。这可能导致应用程序中的其他进程被mpirun发送的信号终止(如此处所述)。

2 个答案:

答案 0 :(得分:3)

高性能标记注意到,在 MPI_Finalize()之前添加return(0) 。此代码将在不提示任何问题的情况下运行......但结果仍然是不正确的。同时,它将打印nan作为结果,这是错误的。

问题来自MPI_Bcast(A,n*n,MPI_DOUBLE,...)A定义为float A[500][500]

  • 您需要广播指向第一个元素&A[0][0]的指针,而不是指向指向第一个元素的指针。
  • 如果您发送n*n个元素(n = 3),则会发送A[0][0],...,A[0][8],而A[1][1]将保持未初始化状态。这可能会导致错误的结果,例如nan。为了简化(懒惰......),你可以改为500*500
  • MPI_DOUBLE对应双精度...解决方案要么更改double A[500][500]MPI_Bcast(&A[0][0],500*500,MPI_FLOAT,...)。对b执行相同的操作。

rand()的确定性使用对于调试目的非常有用...不要忘记使用srand()为随机生成器播种!

编辑:这是代码:

#include<stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>

int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);

    int i,j,k;
    int map[500];
    double A[500][500],b[500],c[500],x[500],sum=0.0;
    double range=1.0;
    int n=3;
    int rank, nprocs;
    clock_t begin1, end1, begin2, end2;
    MPI_Status status;

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);   /* get current process id */
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs); /* get number of processes */

    //////////////////////////////////////////////////////////////////////////////////

    if (rank==0)
    {
        for (i=0; i<n; i++)
        {
            for (j=0; j<n; j++)
                A[i][j]=range*(1.0-2.0*(double)rand()/RAND_MAX);
            b[i]=range*(1.0-2.0*(double)rand()/RAND_MAX);
        }
        printf("\n Matrix A (generated randomly):\n");
        for (i=0; i<n; i++)
        {
            for (j=0; j<n; j++)
                printf("%9.6lf ",A[i][j]);
            printf("\n");
        }
        printf("\n Vector b (generated randomly):\n");
        for (i=0; i<n; i++)
            printf("%9.6lf ",b[i]);
        printf("\n\n");
    }

    //////////////////////////////////////////////////////////////////////////////////

    begin1 =clock();

    MPI_Bcast (&A[0][0],500*500,MPI_DOUBLE,0,MPI_COMM_WORLD);
    MPI_Bcast (b,n,MPI_DOUBLE,0,MPI_COMM_WORLD);    

    for(i=0; i<n; i++)
    {
        map[i]= i % nprocs;
    } 

    for(k=0;k<n;k++)
    {
        MPI_Bcast (&A[k][k],n-k,MPI_DOUBLE,map[k],MPI_COMM_WORLD);
        MPI_Bcast (&b[k],1,MPI_DOUBLE,map[k],MPI_COMM_WORLD);
        for(i= k+1; i<n; i++) 
        {
            if(map[i] == rank)
            {
                c[i]=A[i][k]/A[k][k];
            }
        }               
        for(i= k+1; i<n; i++) 
        {       
            if(map[i] == rank)
            {
                for(j=0;j<n;j++)
                {
                    A[i][j]=A[i][j]-( c[i]*A[k][j] );
                }
                b[i]=b[i]-( c[i]*b[k] );
            }
        }
    }
    end1 = clock();

    //////////////////////////////////////////////////////////////////////////////////

    begin2 =clock();

    if (rank==0)
    { 
        x[n-1]=b[n-1]/A[n-1][n-1];
        for(i=n-2;i>=0;i--)
        {
            sum=0;

            for(j=i+1;j<n;j++)
            {
                sum=sum+A[i][j]*x[j];
            }
            x[i]=(b[i]-sum)/A[i][i];
        }

        end2 = clock();
    }
    //////////////////////////////////////////////////////////////////////////////////
    if (rank==0)
    { 
        printf("\nThe solution is:");
        for(i=0;i<n;i++)
        {
            printf("\nx%d=%f\t",i,x[i]);

        }

        printf("\n\nLU decomposition time: %f", (double)(end1 - begin1) / CLOCKS_PER_SEC);
        printf("\nBack substitution time: %f\n", (double)(end2 - begin2) / CLOCKS_PER_SEC);
    }
    MPI_Finalize();
    return(0);


}

答案 1 :(得分:1)

我不是一个C程序员,但它看起来好像你可能过早地打电话给return。具体来说,您已在MPI_Finalize()之前调用它。尝试交换语句的顺序。甚至完全放弃return