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();
}