Hi All,
I am having a strange problem with the floating precision. I get correct 
precision when I launch with one process, but when the same code is launched 
with 2 or more process I am losing precision in MPI_Redcue(..., MPI_FLOAT, 
MPI_SUM..); call. Output from my code

(admin)host:~$ mpirun -np 1 string 10 0.1 0.9 10 3
sum = 1
sum = 0.999992
sum = 1.00043

(admin)host:~$ mpirun -np 2 string 10 0.1 0.9 10 3
sum = 1
sum = 1
sum = 1.00049

As you can see I am loosing precision. Can someone help me fix this code? Last 
parameter to my code is the number of iterations. I am attaching source code to 
this email.

Santhosh
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"

using namespace std;

#define MASTER 0
int RtoL = 10;
int LtoR = 20;

int main ( int argc, char **argv ) 
{
    int nprocs, taskid;
    FILE *f = NULL;
    int left, right, i_start, i_end;
    float sum = 0;
    MPI_Status status;
    float *y, *yold;
    float *v, *vold;

    //  const int NUM_MASSES = 1000;
    //  const float duration = 10.0;
    //  const float Ktension = 0.1;
    //  const float Kdamping = 0.9;

#if 0
    if ( argc != 5 ) {
        cout << "usage: " << argv[0] << " NUM_MASSES durationInSecs Ktension 
Kdamping\n";
        return 2;
    }
#endif

    int NUM_MASSES  = atoi ( argv[1] );
    float duration = atof ( argv[2] );
    float Ktension = atof ( argv[3] );
    float Kdamping = atof ( argv[4] );
    const int PICKUP_POS = NUM_MASSES / 7;
    const int OVERSAMPLING = 16;

    MPI_Init(&argc,&argv);
    MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&taskid);

    if (taskid  == 0) {
        f = fopen ( "rstring.raw", "wb" );
        if (!f) {
            cout << "can't open output file\n";
            return 1;
        }
    }

    y = new float[NUM_MASSES];
    yold = new float[NUM_MASSES];
    v = new float[NUM_MASSES];

    for (int i = 0; i < NUM_MASSES; i++ ) {
        v[i]  = 0.0;
        yold[i] = y[i] = 0.0;
        if (i == NUM_MASSES/2 )
            yold[i] = 1.0; 
    }

    /*
     * Identifying left and right tasks
     * For task 0   - there is no left task
     * For task n-1 - there is no right task
     */
    if (taskid == 0) {
        left = MPI_PROC_NULL;
        right = 1;
    } else if (taskid == nprocs - 1) {
        left = taskid - 1;
        right = MPI_PROC_NULL;
    } else {
        left = taskid - 1;
        right = taskid + 1;
    }

    i_start = taskid * (NUM_MASSES/nprocs);
    i_end = i_start + (NUM_MASSES/nprocs);
    /*
     * check if there are any left over masses, and assign
     * it to the last process
     */
    if (NUM_MASSES % nprocs) {
        if (taskid == nprocs - 1) {
            i_end = i_end + (NUM_MASSES % nprocs);
        }
    }

    int numIters = duration * 44100 * OVERSAMPLING;;
    if (argc == 6) {
        numIters = atoi(argv[5]);
    }

    for ( int t = 0; t < numIters; t++ ) {
        float sum = 0;
        float gsum = 0;

        for ( int i = i_start; i < i_end; i++ ) {
            if ( i == 0 || i == NUM_MASSES-1 ) {
            } else {
                float accel = Ktension * (yold[i+1] + yold[i-1] - 2*yold[i]);
                v[i] += accel;
                v[i] *= Kdamping;
                y[i] = (float)yold[i] + (float)v[i];
                sum += (float)y[i];
            }
        }

        //printf("taskid = %d iter = %d sum = %f\n", taskid, t, sum);
        //cout<< "taskid = "<<taskid<<" iter = "<<t<<" sum = " << sum << endl;
        MPI_Reduce(&sum, &gsum, 1, MPI_FLOAT, MPI_SUM, MASTER, MPI_COMM_WORLD);

        if (taskid != nprocs - 1) {
            /* Send to the right and receive form the left */
            MPI_Send(&yold[i_end-1],1, MPI_FLOAT, right, LtoR, MPI_COMM_WORLD);
            MPI_Recv(&yold[i_end],  1, MPI_FLOAT, right, RtoL, MPI_COMM_WORLD, 
&status);

            MPI_Send(&y[i_end-1],1, MPI_FLOAT, right, LtoR, MPI_COMM_WORLD);
            MPI_Recv(&y[i_end],  1, MPI_FLOAT, right, RtoL, MPI_COMM_WORLD, 
&status);
        }
        if (taskid != 0) {
            /* Send to the left and receive form the right */
            MPI_Send(&yold[i_start],   1, MPI_FLOAT, left, RtoL, 
MPI_COMM_WORLD);
            MPI_Recv(&yold[i_start-1], 1, MPI_FLOAT, left, LtoR, 
MPI_COMM_WORLD, &status);

            MPI_Send(&y[i_start],   1, MPI_FLOAT, left, RtoL, MPI_COMM_WORLD);
            MPI_Recv(&y[i_start-1], 1, MPI_FLOAT, left, LtoR, MPI_COMM_WORLD, 
&status);
        }

        int tmp_var = 0;
        //cout<<"After Reduce task = "<<taskid<<"y = ";
        for (tmp_var = 0; tmp_var < NUM_MASSES; tmp_var++) {
            //printf("%f ", y[tmp_var]);
            //cout<<y[tmp_var]<<" ";
        }
        //cout<<endl;

        float *tmp = y;
        y = yold;
        yold = tmp;

        if (taskid == 0) {
            cout<< "sum = " << gsum << endl;
            //cout<<"Average Comm Time = 
"<<(total_comm_time/(float)nprocs)<<endl;
            if ( t % OVERSAMPLING == 0 ) {
                fwrite ( &gsum, sizeof(float), 1, f );
            }
        }
    }
    if (taskid  == 0) {
        fclose ( f );
    }
    MPI_Finalize();
}

Reply via email to