Alessandroempire Alessandroempire - 4 years ago 157
C Question

Invalid node count in MPI pi calculation

I am trying to parallelize the following code for calculation of pi.

My approach is to use scatter to parallelize the for, and then use a reduce to calculate the sum value and finally show pi.

My code is the following

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

long num_steps = 100000;
double step = 1.0/100000.0;

int main() {

int i, myid, size;
double x, pi, local_sum = 0.0, sum=0.0;
double send_vec[num_steps], recv_vect[num_steps];

// Initialize the MPI environment
MPI_Comm_size(MPI_COMM_WORLD, &size);

if (myid ==0){
int i=0;
for (i=0; i<num_steps;i++){

MPI_Scatter(send_vec, num_steps/size, MPI_INT, recv_vect,
num_steps, MPI_INT, 0, MPI_COMM_WORLD);

for(i = 0; i < num_steps; ++i) {
x = (recv_vect[i]-0.5)*step;
local_sum += 4.0/(1.0+x*x);

MPI_Reduce(&local_sum, &sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

if (myid == 0){
pi = step*sum;
printf("PI value = %f\n", pi);

// Finalize the MPI environment.

The thing is when I run the program with the option -np 1 and 2
I do get the desired result.

Yet when I run with 3, 4 and higher I get the following error:

PIC_Send(284).........: Negative count, value is -240000
Fatal error in PMPI_Scatter: Invalid count, error stack

Answer Source

The call to MPI_Scatter() is to be corrected:

MPI_Scatter(send_vec, num_steps/size, MPI_INT, recv_vect, 
num_steps, MPI_INT, 0, MPI_COMM_WORLD);
  • To send double, use the datatype MPI_DOUBLE as you did in the MPI_Reduce()
  • Since the sendtype is similar to the recvtype, the number of item sent to each process sendcount must be equal to the number of item received by each process recvcount. In the present case, it's num_steps/size.

Finally, the call to MPI_Scatter() will look like:

MPI_Scatter(send_vec, num_steps/size, MPI_DOUBLE, recv_vect, 
num_steps/size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

Lastly, dynamic memory allocation can be used to avoid using the stack for storing large arrays. Moreover, the allocated space can be decreased so as to reduce the memory footprint:

double* send_vec=NULL;
double* recv_vec=NULL;
   if(send_vec==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
if(recv_vec==NULL){fprintf(stderr,"malloc failed\n");exit(1);}


Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download