Beispiel #1
0
static
void
paralellJacobi(struct calculation_arguments const* arguments, struct calculation_results *results, struct options const* options)
{
    int rank, num_procs;
    MPI_Status status;
    
    
    MPI_Init(arguments->argc, arguments->argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
    
    if(rank == 0)
        calculateMatrices(arguments, num_procs);
    
    int i, j;                                   /* local variables for loops  */
    int m1, m2;                                 /* used as indices for old and new matrices       */
    double star;                                /* four times center value minus 4 neigh.b values */
    double residuum;                            /* residuum of current iteration                  */
    double maxresiduum;                         /* maximum residuum value of a slave in iteration */
    
    int const N = arguments->N;
    double const h = arguments->h;
    
    double pih = 0.0;
    double fpisin = 0.0;
    
    int term_iteration = options->term_iteration;
    
    int sendRec_before = (rank - 1) % num_procs;
    int sendRec_after = rank + 1 % num_procs;
    m1 = 0;
    m2 = 1;
    
    
    if (options->inf_func == FUNC_FPISIN)
    {
        pih = PI * h;
        fpisin = 0.25 * TWO_PI_SQUARE * h * h;
    }
    
    while (term_iteration > 0)
    {
        double** Matrix_Out = getMyMatrix(arguments->start[rank], arguments->moveSize[rank], m1, arguments);
        double** Matrix_In  = getMyMatrix(arguments->start[rank], arguments->moveSize[rank], m2, arguments);
        
        maxresiduum = 0;
        
        
        if ((rank % 2) == 0)
        {
            if (rank == 0)
            {
                /*TODO: Sendplätze überprüfen, Sendetypen überprüfen */
                MPI_Send(&Matrix_In[arguments->moveSize[rank] - 1], 1, MPI_DOUBLE, sendRec_after, TAG_SEND, MPI_COMM_WORLD);
                MPI_Recv(&Matrix_In[arguments->moveSize[rank]], 1, MPI_DOUBLE,sendRec_after, TAG_RECV, MPI_COMM_WORLD, NULL);
                
            }
            else if (rank == num_procs -1)
            {
                MPI_Send(&Matrix_In[arguments->moveSize[rank] - 1], 1, MPI_DOUBLE, sendRec_before, TAG_SEND, MPI_COMM_WORLD);
                MPI_Recv(&Matrix_In[0], 1, MPI_DOUBLE,  sendRec_before, TAG_RECV, MPI_COMM_WORLD, NULL);
            }
            else
            {
                MPI_Send(&Matrix_In[1], 1, MPI_DOUBLE, sendRec_before, TAG_SEND, MPI_COMM_WORLD);
                MPI_Send(&Matrix_In[arguments->moveSize[rank] - 1], 1, MPI_DOUBLE, sendRec_after, TAG_SEND, MPI_COMM_WORLD);
                MPI_Recv(&Matrix_In[0], 1, MPI_DOUBLE,  sendRec_after, TAG_RECV, MPI_COMM_WORLD, NULL);
                MPI_Recv(&Matrix_In[arguments->moveSize[rank]], 1, MPI_DOUBLE,  sendRec_before, TAG_RECV, MPI_COMM_WORLD, NULL);
            }
        }
        else
        {
            if (rank == num_procs - 1)
            {
                MPI_Recv(&Matrix_In[0], 1, MPI_DOUBLE,  sendRec_before, TAG_RECV, MPI_COMM_WORLD, NULL);
                MPI_Send(&Matrix_In[arguments->moveSize[rank] - 1], 1, MPI_DOUBLE, sendRec_before, TAG_SEND, MPI_COMM_WORLD);
            }
            else
            {
                MPI_Recv(&Matrix_In[0], 1, MPI_DOUBLE,  sendRec_after, TAG_RECV, MPI_COMM_WORLD, NULL);
                MPI_Recv(&Matrix_In[arguments->moveSize[rank]], 1, MPI_DOUBLE,  sendRec_before, TAG_RECV, MPI_COMM_WORLD, NULL);
                MPI_Send(&Matrix_In[1], 1, MPI_DOUBLE, sendRec_before, TAG_SEND, MPI_COMM_WORLD);
                MPI_Send(&Matrix_In[arguments->moveSize[rank] - 1], 1, MPI_DOUBLE, sendRec_after, TAG_SEND, MPI_COMM_WORLD);
            }
        }
        
        
        
        /* over all rows */
        for (i = 1; i < arguments->moveSize[rank]; i++)
        {
            double fpisin_i = 0.0;
            
            if (options->inf_func == FUNC_FPISIN)
            {
                fpisin_i = fpisin * sin(pih * (double)i);
            }
            
            /* over all columns */
            for (j = 1; j < N; j++)
            {
                star = 0.25 * (Matrix_In[i-1][j] + Matrix_In[i][j-1] + Matrix_In[i][j+1] + Matrix_In[i+1][j]);
                
                if (options->inf_func == FUNC_FPISIN)
                {
                    star += fpisin_i * sin(pih * (double)j);
                }
                
                if (options->termination == TERM_PREC || term_iteration == 1)
                {
                    residuum = Matrix_In[i][j] - star;
                    residuum = (residuum < 0) ? -residuum : residuum;
                    maxresiduum = (residuum < maxresiduum) ? maxresiduum : residuum;
                }
                
                Matrix_Out[i][j] = star;
            }
        }
        
        results->stat_iteration++;
        results->stat_precision = maxresiduum;
        
        
        /* exchange m1 and m2 */
        i = m1;
        m1 = m2;
        m2 = i;
        
        
        
        /* check for stopping calculation, depending on termination method */
        if (options->termination == TERM_PREC)
        {
            if (maxresiduum < options->term_precision)
            {
                term_iteration = 0;
            }
        }
        else if (options->termination == TERM_ITER)
        {
            term_iteration--;
        }
    }
    
    DisplayMatrixMPI(arguments, results, options, rank, num_procs, arguments->start[rank], (arguments->moveSize[rank] + arguments->start[rank]));
    
    results->m = m2;
}
Beispiel #2
0
/* ************************************************************************ */
int
main (int argc, char** argv)
{
    int rank;
    int size;
    int rest;
    int from, to;

    MPI_Init(&argc, &argv);

    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    struct options options;
    struct calculation_arguments arguments;
    struct calculation_results results;

    /* Parameter nur einmal abfragen */
    if(rank == 0)
    {
        AskParams(&options, argc, argv);
    }
    MPI_Bcast(&options, (sizeof(options)), MPI_BYTE, MASTER, MPI_COMM_WORLD);

    initVariables(&arguments, &results, &options);

    /* Damit allocation + initialization richtig läuft, wird für GS size = 1 gesetzt */
    if(options.method == METH_GAUSS_SEIDEL)
    {
        size = 1;
    }

    /* Aufteilen bis auf rest */
    int N_part = arguments.N;
    int lines = N_part - 1;
    rest = lines % size;
    N_part = (lines - rest) / size;

    /* globale zeilennummer berechnen, hier wird der rest beachtet						*/
    /* offset ist (rank + 1) für rank < rest, steigt also linear mit steigendem rang 	*/
    if(rank < rest)
    {
        from = N_part * rank 		+ rank + 1;
        to = N_part * (rank + 1) 	+ (rank + 1);
    }
    /* offset hier ist rest also die der maximale offset von oben */
    else
    {
        from = N_part * rank 		+ rest + 1;
        to = N_part * (rank + 1) 	+ rest ;
    }
    arguments.to = to;
    arguments.from = from;


    /* at least we only need N - 1 processes for calculation */
    if((unsigned int)size > (arguments.N -1))
    {
        size = (arguments.N - 1);

        if(rank == MASTER )
        {
            printf("\nWarning, you are using more processes than rows.\n This can slow down the calculation process! \n\n");
        }

    }

    //calculate Number of Rows
    arguments.numberOfRows = ((to - from + 1) > 0 ) ? (to - from + 1) : 0;

    allocateMatrices(&arguments);
    initMatrices(&arguments, &options, rank, size);

    gettimeofday(&start_time, NULL);                   /*  start timer         */


    if (options.method == METH_JACOBI )
    {
        calculateJacobi(&arguments, &results, &options, rank, size);
    }
    else
    {
        /* GS berechnet nur MASTER */
        if(rank == MASTER)
        {
            printf("\nGS wird nur sequentiell berechnet! \n");
            calculate(&arguments, &results, &options);
        }
    }

    gettimeofday(&comp_time, NULL);                   /*  stop timer          */

    /* only once */
    if(rank == MASTER)
    {
        displayStatistics(&arguments, &results, &options, size);
    }

    /* GS macht alte ausgabe */
    if((options.method == METH_GAUSS_SEIDEL) && (rank == MASTER))
    {
        DisplayMatrix(&arguments, &results, &options);
    }
    else
    {
        DisplayMatrixMPI(&arguments, &results, &options, rank, size, from, to);
    }

    freeMatrices(&arguments);                                       /*  free memory     */

    MPI_Finalize();
    return 0;
}