1

I am trying to parallelize the Mandelbrot. the correct output should be around 1.510659. however I am not getting that correctly.

** PROGRAM: Mandelbrot area ** ** PURPOSE: Program to compute the area of a Mandelbrot set. ** The correct answer should be around 1.510659. ** ** USAGE: Program runs without input ... just run the executable ** reduction for numoutside.

this is my parallelized code

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

#define NPOINTS 1000
#define MAXITER 1000
int P = 1;
struct d_complex
{
  double r;
  double i;
};

int testpoint(struct d_complex);

struct d_complex c;
struct d_complex cPart;
int numoutside = 1;

int main()
{
  int i, j, row;
    int res;
  double area, error, eps = 1.0e-5;
  int myrank, mysize;
  double stsec, ensec, commtime, maxcommtime;
  MPI_Status status;
  MPI_Init(NULL, NULL);
  MPI_Comm_size(MPI_COMM_WORLD, &mysize);
  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
  stsec = MPI_Wtime();
  //   Loop over grid of points in the complex plane which contains the Mandelbrot set,
  //   testing each point to see whether it is inside or outside the set.
  /*for (i = 0; i < NPOINTS; i ++)
  {
    for (j = 0; j < NPOINTS ; j++)
    {
      c.r = -2.0 + 2.5 * (double)(i) / (double)(NPOINTS) + eps;
      c.i = 1.125 * (double)(j) / (double)(NPOINTS) + eps;
      testpoint(c);
    }
  }*/

  if (myrank == 0)
  {
  

    /* Begin User Program  - the master */
    //*
    int outsum, nb_pixel = NPOINTS*NPOINTS ;
    for (i = 0; i < nb_pixel; i++)
    {
      MPI_Recv(&res, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
      // printf("Slave id %d has send : %d \n", status.MPI_SOURCE, data[2]);
      // printf("%d: [%d,%d] -> [%d,%d] = %d\n", status.MPI_SOURCE, data[0], data[1], data[0] + MAXX, data[1] + MAXY, data[2]);
      res += numoutside;
    }
     area = 2.0 * 2.5 * 1.125 * (double)(NPOINTS * NPOINTS - res) / (double)(NPOINTS * NPOINTS);
   error = area / (double)NPOINTS;
    printf("Area of Mandlebrot set = %12.8f +/- %12.8f\n", area, error);
    printf("Finish.\n");
  }
  else
  {
   
    for (i = myrank; i < NPOINTS; i+=mysize)
    {
      for (j = 0; j < NPOINTS; j++)
      {
        c.r = -2.0 + 2.5 * (double)(i) / (double)(NPOINTS) + eps;
        c.i = 1.125 * (double)(j) / (double)(NPOINTS) + eps;
        res=testpoint(c);
         MPI_Send(&res, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
      }
    }
  }

  // Calculate area of set and error estimate and output the results

  MPI_Finalize();
  ensec = MPI_Wtime();
  commtime = ensec - stsec;
  // area = 2.0 * 2.5 * 1.125 * (double)(NPOINTS * NPOINTS - numoutside) / (double)(NPOINTS * NPOINTS);
  // error = area / (double)NPOINTS;
  printf("Area of Mandlebrot set = %12.8f +/- %12.8f\n", area, error);

  if (myrank == 0)
  {
    printf("%.3f\n", commtime);
  }
}

int testpoint(struct d_complex c)
{

  // Does the iteration z=z*z+c, until |z| > 2 when point is known to be outside set
  // If loop count reaches MAXITER, point is considered to be inside the set

  struct d_complex z;
  int iter;
  double temp;

  z = c;
  for (iter = 0; iter < MAXITER; iter++)
  {
    temp = (z.r * z.r) - (z.i * z.i) + c.r;
    z.i = z.r * z.i * 2 + c.i;
    z.r = temp;
    if ((z.r * z.r + z.i * z.i) > 4.0)
    {
      // MPI_Send( &numoutside, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
      return numoutside;
      break;
    }
  }
  return 0;
}

the expectation is to get around 1.510659 when running the code with NPOINTS: 1000,2000 and 2,4, processors .

Mohammed
  • 11
  • 2
  • 1
    *ADDITIONAL EXERCISES: Experiment with the schedule clause to fix the load imbalance. Experiment with atomic vs. critical vs. reduction for numoutside* Are you sure you shouldn't be using OpenMP? – High Performance Mark Dec 09 '22 at 18:00
  • yes , it should be MPI. that was just a comment on the code – Mohammed Dec 09 '22 at 19:09
  • `res += numoutside` does not make any sense to me. rank `0` must do its share of work. Assuming you want to sum the number of points, compute the partial sum on each rank and send it once (or even better, use `MPI_Reduce()`) instead of sending for each pixel. – Gilles Gouaillardet Dec 10 '22 at 02:33
  • Keep in mind that your program should produce the correct result even if running a single MPI task. – Gilles Gouaillardet Dec 10 '22 at 02:35

0 Answers0