Commit d7a94ec6 authored by Luca Tornatore's avatar Luca Tornatore
Browse files

fixed bugs, typos; cleaned-up everything

parent 62ee1e7e
Loading
Loading
Loading
Loading
+55 −95
Changes for OpenMP/exercises/Mandelbrot/.backups/mandelbrot.omp.c.pre_split: 55 added lines, 95 removed lines.
Original line number Diff line number Diff line
@@ -133,6 +133,9 @@ print_usage (char *program_name // executable name from argv[0]
           "  --dx-factor VALUE   accepted for interface compatibility         (%u)\n"
           "  --dy-factor VALUE   number of serial horizontal work stripes     (%u)\n"
           "  --kmax VALUE        maximum Mandelbrot iteration count           (%u)\n"
	   "  --mode VALUE        0: omp for schedule(static)\n"
	   "                      n > 0: omp for schedule(static,n)\n"
	   "                      n < 0: omp for schedule(dynamic, -n)\n"
           "  --output FILE       output PNG file                              (%s)\n"
           "  --help              show this help message\n"
           "\n"
@@ -239,11 +242,16 @@ parse_unsigned_option ( int argc, // number of command-line tokens
  return 0;
}


/*
  Parse an integer option of the form "--name value".
  It is used for ppu, factors, and kmax.
*/
static int
parse_positive_option ( int            argc,    // number of command-line tokens
			char         **argv,    // command-line token vector
			int           *i,       // index of the option currently being parsed
			unsigned int  *value    // destination for the parsed integer value
			int           *value    // destination for the parsed integer value
			)
{
  char          *endptr;
@@ -260,19 +268,54 @@ parse_positive_option ( int argc, // number of command-line tokens
  parsed = strtoul (argv[*i + 1], &endptr, 10);

  if (errno != 0 || endptr == argv[*i + 1] || *endptr != '\0'
      || parsed < 0 || parsed > UINT_MAX)
      || parsed > 1)
    {
      fprintf (stderr, "Invalid integer value for %s: %s\n",
               argv[*i], argv[*i + 1]);
      return -1;
    }

  *value = (unsigned int) parsed;
  *value = (int) parsed;
  *i += 1;

  return 0;
}


static int
parse_string_option ( int            argc,    // number of command-line tokens
		      char         **argv,    // command-line token vector
		      int           *i,       // index of the option currently being parsed
		      int           *value    // destination for the parsed integer value
		      )
{
  if (*i + 1 >= argc)
    {
      fprintf (stderr, "Missing value after %s\n", argv[*i]);
      return -1;
    }

  // get the strlen
  int len = strlen( argv[*i+1] );
  
  // convert on lower case
  for ( int c = 0; c < len; c++ )
    argv[*i+1]+c = lower(argv[*i+1]+c);
  
  // compare with admissible values
  if ( strncmp( "pgm", argv[*i+1], 3 ) == 0 )
    *value = _MANDEL_PGM_;
  else if ( strncmp( "png", argv[*i+1], 3 ) == 0 )
    *value = _MANDEL_PNG_;
  else
    *value = _MANDEL_FORMAT_ERR_

  *i += 1;

  return 0;
}


/*
  Parse all command-line options.  
*/
@@ -542,86 +585,6 @@ colour_from_iteration (unsigned int iteration, // escape iteration count
  rgb[2] = (unsigned char) (255.0 * 8.5 * one_minus_t * one_minus_t * one_minus_t * t);
}

/*
  Render a contiguous horizontal range of rows.
  This is a serial version of the stripe unit used in Track A: it is a simple implementation,
  but this function makes the future producer-consumer decomposition almost there.
*/
static void
render_stripe (options_t        *options,       // view and iteration options
	       image_geometry_t *geometry,      // image dimensions and pixel spacing
	       unsigned int      row_begin,     // first row included in this stripe
	       unsigned int      row_end,       // first row after this stripe
	       unsigned char    *image,         // complete row-major RGB image buffer
	       render_stats_t   *stats          // diagnostics accumulated over the image
	       )
{

  uint64_t     local_checksum;
  uint64_t     local_total_iterations;
  uint64_t     local_inside_pixels;

  local_checksum = stats->checksum;
  local_total_iterations = stats->total_iterations;
  local_inside_pixels = stats->inside_pixels;

  for (unsigned int row = row_begin; row < row_end; ++row)
    {
      // Row zero is the top of the image, hence the minus sign from ymax.
      double ci = options->ymax - ((double) row + 0.5) * geometry->dy;

      for (unsigned col = 0; col < geometry->width; ++col)
        {
          double cr = options->xmin + ((double) col + 0.5) * geometry->dx;
          unsigned int iteration = mandelbrot_escape (cr, ci, options->kmax);

          size_t pixel_offset = ((size_t) row * (size_t) geometry->width
				 + (size_t) col) * 3u;
	  
          colour_from_iteration (iteration, options->kmax, &image[pixel_offset]);

          local_checksum = checksum_update_uint (local_checksum, iteration);
          local_total_iterations += (uint64_t) iteration;

          if (iteration >= options->kmax)
            local_inside_pixels += 1u;
        }
    }

  stats->checksum = local_checksum;
  stats->total_iterations = local_total_iterations;
  stats->inside_pixels = local_inside_pixels;
}

/*
  Render the full image by visiting dy_factor horizontal stripes in order.
*/
static void
render_image_bystripes (options_t        *options,     // view, factors, and kmax
			image_geometry_t *geometry,    // image dimensions and pixel spacing
			unsigned char    *image,       // complete row-major RGB image buffer
			render_stats_t   *stats        // output diagnostics
			)
{
  unsigned int stripe;
  unsigned int row_begin;
  unsigned int row_end;

  stats->checksum = FNV_OFFSET_BASIS;
  stats->total_iterations = 0u;
  stats->inside_pixels = 0u;

  for (stripe = 0; stripe < options->dy_factor; ++stripe)
    {
      row_begin = (unsigned int) (((uint64_t) stripe * geometry->height)
                                  / options->dy_factor);
      row_end = (unsigned int) (((uint64_t) (stripe + 1u) * geometry->height)
                                / options->dy_factor);

      if (row_begin < row_end)
        render_stripe (options, geometry, row_begin, row_end, image, stats);
    }
}

static void
render_image (options_t        *options,     // view, factors, and kmax
@@ -658,23 +621,24 @@ render_image (options_t *options, // view, factors, and kmax
    double mytime       = CPU_TIME_T;
    double my_calc_time = 0;

    if ( options->mode == 1)
    if ( options->mode == 0)
      {
	sprintf( schedule_type, "static, max chunk" );
       #pragma omp for nowait
       #include "loop.h"
       #include "mandelbrot_loop.h"
      }
    else if (options->mode == 2)
    else if (options->mode > 0)
      {
	sprintf( schedule_type, "static, 1-line chunk" );
       #pragma omp for schedule(static, 1) nowait
       #include "loop.h"
	sprintf( schedule_type, "static, %d-line chunk", options->mode);
       #pragma omp for schedule(static, options->mode) nowait
       #include "mandelbrot_loop.h"
      }
    else
      {
	options->mode *= -1;
	sprintf( schedule_type, "dynamic, %d points chunk", options->mode );
       #pragma omp for collapse(2) schedule(dynamic, options->mode) nowait
       #include "loop.h"
       #include "mandelbrot_loop.h"
      }
    
    mytime = CPU_TIME_T - mytime;
@@ -847,17 +811,13 @@ main (int argc, // number of command-line tokens
               "this serial stripe baseline does not use it.\n");
    }

  if ( options.mode == 0 )
    render_image_bystripes (&options, &geometry, image, &stats);
  else
    {
 #if defined(PROFILE)
  timage = (unsigned char *) malloc (image_bytes);
  render_image (&options, &geometry, image, timage);
 #else
  render_image (&options, &geometry, image);
 #endif
    }
 

  if (write_ppm_image (image, geometry.width, geometry.height, options.output_path) != 0)
    {
+688 −0

File added.

Preview size limit exceeded, changes collapsed.

+248 −0
Changes for OpenMP/exercises/Mandelbrot/.backups/mandelbrot_serial.c.pre_fix: 248 added lines, 0 removed lines.
Original line number Diff line number Diff line



/* ────────────────────────────────────────────────────────────────────────── *
│                                                                            │
│ This file is part of the exercises for the Lectures on                     │
│   "Foundations of High Performance Computing"                              │
│ given at                                                                   │
│   Master in HPC and                                                        │
│   Master in Data Science and Scientific Computing                          │
│ @ SISSA, ICTP and University of Trieste                                    │
│                                                                            │
│ contact: luca.tornatore@inaf.it                                            │
│                                                                            │
│     This is free software; you can redistribute it and/or modify           │
│     it under the terms of the GNU General Public License as published by   │
│     the Free Software Foundation; either version 3 of the License, or      │
│     (at your option) any later version.                                    │
│     This code is distributed in the hope that it will be useful,           │
│     but WITHOUT ANY WARRANTY; without even the implied warranty of         │
│     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          │
│     GNU General Public License for more details.                           │
│                                                                            │
│     You should have received a copy of the GNU General Public License      │
│     along with this program.  If not, see <http://www.gnu.org/licenses/>   │
│                                                                            │
* ────────────────────────────────────────────────────────────────────────── */



/*
  Serial Mandelbrot renderer for the HPC final-exam exercise.

  This file is a clean serial baseline, whose goal is to give a correct
  and readable starting point from which introduce MPI work
  dispatch, OpenMP scheduling, optimization experiments, and different tile
  granularities.

  The program implements a command-line parsing, computes every pixel by
  direct iteration, stores the image in a row-major RGB  buffer, and
  writes either a PGM file through a tiny PGM writer, or a png file using
  the stb header.

  Have fun.
*/


#include "mandelbrot_serial.h"


/* ========================================================================================

   : ------------------------------------------------------ :
   :  CALCULATION FUNCTIONS                                 :
   : ------------------------------------------------------ :
 */ 

/*
  Compute the Mandelbrot escape iteration for one point c = cr + i ci.  This
  is the direct scalar kernel, clean, keeps the operation count easy to read.
  This can be heavility optimized.
*/
static unsigned int
mandelbrot_escape (double       cr,      // real part of the pixel centre
		   double       ci,      // imaginary part of the pixel centre
		   unsigned int kmax     // maximum number of iterations
		   )
{
           double zr;
           double zi;
           double zr_next;
           double zr2;
           double zi2;
  unsigned int    k;

  zr = 0.0;
  zi = 0.0;
  k = 0;

  while (k < kmax)
    {
      zr2 = zr * zr;
      zi2 = zi * zi;
      
      if (zr2 + zi2 > 4.0)
        break;
      
      zr_next = zr2 - zi2 + cr;
      zi = 2.0 * zr * zi + ci;
      zr = zr_next;
      k += 1;
    }

  return k;
}

/*
  Map one iteration count to an RGB colour.  Interior points are black.  The
  outside palette is deliberately simple.
  It might be fun experimenting by advanced colouring or smooth-potential formulas.
  Don't be distracted by this, though
  
*/
static void
colour_from_iteration (unsigned int    iteration,    // escape iteration count
		       unsigned int    kmax,         // maximum iteration count
		       unsigned char  *rgb           // output triplet: red, green, blue
		       )
{
  double t;
  double one_minus_t;

  if (iteration >= kmax)
    {
      rgb[0] = 0u;
      rgb[1] = 0u;
      rgb[2] = 0u;
      return;
    }

  t = (double) iteration / (double) kmax;
  one_minus_t = 1.0 - t;

  rgb[0] = (unsigned char) (255.0 * 9.0 * one_minus_t * t * t * t);
  rgb[1] = (unsigned char) (255.0 * 15.0 * one_minus_t * one_minus_t * t * t);
  rgb[2] = (unsigned char) (255.0 * 8.5 * one_minus_t * one_minus_t * one_minus_t * t);
}


static void
render_image (options_t        *options,     // view, factors, and kmax
	      image_geometry_t *geometry,    // image dimensions and pixel spacing
	      unsigned char    *image        // complete row-major RGB image buffer
	      )
{

  uint64_t Nrows = geometry->height;
  uint64_t Ncols = geometry->width;

  for ( int row = 0; row < Nrows; row++ )      
    for ( int col = 0; col < Ncols; col++ )
      {
	double ci = options->ymax - ((double) row + 0.5) * geometry->dy;
	double cr = options->xmin + ((double) col + 0.5) * geometry->dx;
	
	unsigned int iteration = mandelbrot_escape (cr, ci, options->kmax);
	
	size_t pixel_offset    = ((size_t) row * (size_t) geometry->width +
				  (size_t) col) * 3u;
	
	colour_from_iteration (iteration, options->kmax, &image[pixel_offset]);     
      }

  return;
}




/* ========================================================================================

/*
  Program entry point.
*/
int
main (int    argc,    // number of command-line tokens
      char **argv     // command-line token vector
      )
{
  options_t         options;
  image_geometry_t  geometry;
  render_stats_t    stats;
  unsigned char    *image;
  size_t            image_bytes;
  int               parse_status;
  double            inside_fraction;
  double            average_iterations;
  uint64_t          pixel_count;

  set_default_options (&options);
  parse_status = parse_command_line (argc, argv, &options);

  if (parse_status > 0)
    return EXIT_SUCCESS;

  if (parse_status < 0 || validate_options (&options) != 0
      || make_geometry (&options, &geometry) != 0)
    return EXIT_FAILURE;

  if ((size_t) geometry.width > SIZE_MAX / (size_t) geometry.height
      || (size_t) geometry.width * (size_t) geometry.height > SIZE_MAX / 3u)
    {
      fprintf (stderr, "Image is too large for this platform\n");
      return EXIT_FAILURE;
    }

  image_bytes = (size_t) geometry.width * (size_t) geometry.height * 3u;
  image = (unsigned char *) malloc (image_bytes);

  if (image == NULL)
    {
      fprintf (stderr, "Unable to allocate image buffer (%zu bytes)\n", image_bytes);
      return EXIT_FAILURE;
    }

  fprintf (stderr,
           "Rendering %u x %u pixels, kmax = %u, view = [%.17g, %.17g] x [%.17g, %.17g]\n",
           geometry.width, geometry.height, options.kmax,
           options.xmin, options.xmax, options.ymin, options.ymax);

  if (options.dx_factor != DEFAULT_DX_FACTOR)
    {
      fprintf (stderr,
               "Note: --dx-factor is accepted for assignment-interface compatibility; "
               "this serial stripe baseline does not use it.\n");
    }

  
  render_image (&options, &geometry, image, &stats);

  int errio;
  
  if ( options.ioformat == PPM )
    errio = write_ppm_image (image, geometry.width, geometry.height, options.output_path);
  else if ( options.ioformat == PNG )
    errio = write_png_rgb8 (options.output_path, geometry.width, geometry.height, image);

  free(image);
  
  if ( errio != 0)
    return EXIT_FAILURE;

  pixel_count        = (uint64_t) geometry.width * (uint64_t) geometry.height;
  inside_fraction    = (double) stats.inside_pixels / (double) pixel_count;
  average_iterations = (double) stats.total_iterations / (double) pixel_count;

  printf ("output_file              %s\n", options.output_path);
  printf ("width                    %u\n", geometry.width);
  printf ("height                   %u\n", geometry.height);
  printf ("kmax                     %u\n", options.kmax);
  printf ("iteration_checksum       %016llx\n", (unsigned long long) stats.checksum);
  printf ("inside_pixels            %llu\n", (unsigned long long) stats.inside_pixels);
  printf ("inside_fraction          %.17g\n", inside_fraction);
  printf ("average_iterations       %.17g\n", average_iterations);
  printf ("total_iterations         %llu\n", (unsigned long long) stats.total_iterations);

  return EXIT_SUCCESS;
}
+148 −0
Changes for OpenMP/exercises/Mandelbrot/.backups/mandelbrot_serial.h.pre_fix: 148 added lines, 0 removed lines.
Original line number Diff line number Diff line

/* ────────────────────────────────────────────────────────────────────────── *
│                                                                            │
│ This file is part of the exercises for the Lectures on                     │
│   "Foundations of High Performance Computing"                              │
│ given at                                                                   │
│   Master in HPC and                                                        │
│   Master in Data Science and Scientific Computing                          │
│ @ SISSA, ICTP and University of Trieste                                    │
│                                                                            │
│ contact: luca.tornatore@inaf.it                                            │
│                                                                            │
│     This is free software; you can redistribute it and/or modify           │
│     it under the terms of the GNU General Public License as published by   │
│     the Free Software Foundation; either version 3 of the License, or      │
│     (at your option) any later version.                                    │
│     This code is distributed in the hope that it will be useful,           │
│     but WITHOUT ANY WARRANTY; without even the implied warranty of         │
│     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          │
│     GNU General Public License for more details.                           │
│                                                                            │
│     You should have received a copy of the GNU General Public License      │
│     along with this program.  If not, see <http://www.gnu.org/licenses/>   │
│                                                                            │
* ────────────────────────────────────────────────────────────────────────── */



/*
  Serial Mandelbrot renderer for the HPC final-exam exercise.

  This file is a clean serial baseline, whose goal is to give a correct
  and readable starting point from which introduce MPI work
  dispatch, OpenMP scheduling, optimization experiments, and different tile
  granularities.

  The program implements a command-line parsing, computes every pixel by
  direct iteration, stores the image in a row-major RGB  buffer, and
  writes either a PGM file through a tiny PGM writer, or a png file using
  the stb header.

  Have fun.
*/

#include <errno.h>
#include <limits.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>



#define _MANDEL_ERR_ ((uint32_t)-1)

#define _MANDEL_PGM_ 0
#define _MANDEL_PNG_ 1
#define NIMAGEFORMATS 2


#define DEFAULT_XMIN       (-2.5)
#define DEFAULT_XMAX       (1.5)
#define DEFAULT_YMIN       (-2.0)
#define DEFAULT_YMAX       (2.0)
#define DEFAULT_PPU        (256u)
#define DEFAULT_DX_FACTOR  (8u)
#define DEFAULT_DY_FACTOR  (8u)
#define DEFAULT_KMAX       (1024u)
#define DEFAULT_FORMAT     _MANDEL_PGM_
#define DEFAULT_FMT_NAME   "PGM"
#define DEFAULT_OUTPUT     "mandelbrot.pgm"

#define FNV_OFFSET_BASIS   (1469598103934665603ULL)
#define FNV_PRIME          (1099511628211ULL)

/*
  Runtime options shared by the serial baseline and by the future parallel
  implementations.  The dx_factor entry is parsed for launcher compatibility
  with the assignment interface, although the serial stripe strategy does not
  need it.
*/
typedef struct
{
  double            xmin;
  double            xmax;
  double            ymin;
  double            ymax;
  unsigned int      ppu;
  unsigned int      dx_factor;
  unsigned int      dy_factor;
  unsigned int      kmax;
  unsigned int      format;
  char             *output_path;
} options_t;


/*
  Image geometry after converting the continuous complex-plane window into a
  discrete pixel grid.
  Pixels are addressed as (row, column), with row zero at the top of the image,
  consistently with the --ymax upper-left convention.
*/
typedef struct
{
  unsigned int      width;
  unsigned int      height;
  double            dx;
  double            dy;
} image_geometry_t;

/*
  Lightweight diagnostics printed at the end of the run.
  The checksum is just useful reproducibility check: if two runs
  have the same options, compiler, and arithmetic behaviour, they should report
  the same value.
*/
typedef struct
{
  uint64_t          checksum;
  uint64_t          total_iterations;
  uint64_t          inside_pixels;
} render_stats_t;



char *mandelbrot_image_formats[NIMAGEFORMATS] = {"pgm", "png" };


static void print_usage (char *);

static void set_default_options (options_t *);

static int  parse_double_option ( int, char **, int  *, double * );

static int  parse_unsigned_option ( int, char **, int  *, unsigned int * );

//static int  parse_double_option ( int, char **, int  *, char **, int, unsigned int * );

static int  parse_command_line  ( int, char **, options_t  * );

static int  validate_options    (options_t * );

static int  make_geometry       ( options_t *, image_geometry_t * );

static uint64_t checksum_update_uint (uint64_t, unsigned int );

static int write_ppm_image( const void * restrict, const int, const int, const char * restrict );
Loading