Home > database >  OpenMP problem with mandelbrot program in c
OpenMP problem with mandelbrot program in c

Time:11-03

I have to parallelize using openMP the serial version of a program in C to visualize a Mandelbrot set. I tried to do it but I obtain something really strange. I know there is something wrong with the declaration of variables into parallel for, but i don't get what's the problem

Do you have any suggestion?

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>

#include "pngwriter.h"
#include "consts.h"


unsigned long get_time()
{
    struct timeval tp;
    gettimeofday(&tp, NULL);
    return tp.tv_sec * 1000000   tp.tv_usec;
}

int main(int argc, char** argv)
{
    png_data* pPng = png_create(IMAGE_WIDTH, IMAGE_HEIGHT);

    double x, y, x2, y2, cx, cy;
    cy = MIN_Y;

    double fDeltaX = (MAX_X - MIN_X) / (double)IMAGE_WIDTH;
    double fDeltaY = (MAX_Y - MIN_Y) / (double)IMAGE_HEIGHT;

    long nTotalIterationsCount = 0;
    unsigned long nTimeStart = get_time();

    long i, j, n;

    n = 0;
    int c;

#pragma omp parallel
    {
#pragma omp for private( i,c) reduction(  : cx,cy)
        for (j = 0; j < IMAGE_HEIGHT; j  ) {
            cx = MIN_X;

            for (i = 0; i < IMAGE_WIDTH; i  ) {
                x = cx;
                y = cy;

                x2 = x * x;
                y2 = y * y;

                for (n = 0; (n < MAX_ITERS) && (x2   y2 < 4); n  ) {
             
                    y = 2 * x * y   cy;
                    x = x2 - y2   cx;
                    x2 = x * x;
                    y2 = y * y;
                }

                int c = ((long)n * 255) / MAX_ITERS;
                png_plot(pPng, i, j, c, c, c);

                cx  = fDeltaX;

                nTotalIterationsCount  ;
            }

            cy  = fDeltaY;
        }
    }

    unsigned long nTimeEnd = get_time();

  // print benchmark data
  printf("Total time:                 %g millisconds\n",
         (nTimeEnd - nTimeStart) / 1000.0);
  printf("Image size:                 %ld x %ld = %ld Pixels\n",
         (long)IMAGE_WIDTH, (long)IMAGE_HEIGHT,
         (long)(IMAGE_WIDTH * IMAGE_HEIGHT));
  printf("Total number of iterations: %ld\n", nTotalIterationsCount);
  printf("Avg. time per pixel:        %g microseconds\n",
         (nTimeEnd - nTimeStart) / (double)(IMAGE_WIDTH * IMAGE_HEIGHT));
  printf("Avg. time per iteration:    %g microseconds\n",
         (nTimeEnd - nTimeStart) / (double)nTotalIterationsCount);
  printf("Iterations/second:          %g\n",
         nTotalIterationsCount / (double)(nTimeEnd - nTimeStart) * 1e6);
  // assume there are 8 floating point operations per iteration
  printf("MFlop/s:                    %g\n",
         nTotalIterationsCount * 8.0 / (double)(nTimeEnd - nTimeStart));

  png_write(pPng, "mandel.png");
  return 0;
}

My output:

image

CodePudding user response:

As already pointed out by @paddy you have to calculate cy directly using the equation cy = MIN_Y j * fDeltaY; and get rid of many shared variables, as they cause data race. Generally, it is always recommended to define your variables in their minimal required scope. I also suggest to calculate cx similarly (cx = MIN_X i * fDeltaX;) it makes possible to use collapse(2) clause in your #pragma omp for directive and IMO it is also easier to understand your code. You should use reduction in case of nTotalIterationsCount only. Please also make sure that png_plot is threadsafe. The code should look something like this:

#pragma omp parallel for reduction(  : nTotalIterationsCount) 
    for (long j = 0; j < IMAGE_HEIGHT; j  ) {            
        for (long i = 0; i < IMAGE_WIDTH; i  ) {
            double cx = MIN_X   i * fDeltaX;            
            double cy = MIN_Y   j * fDeltaY;
            double x = cx;
            double y = cy;
            double x2 = x * x;
            double y2 = y * y;
            long n;
            for (n=0; (n < MAX_ITERS) && (x2   y2 < 4); n  ) {             
                y = 2 * x * y   cy;
                x = x2 - y2   cx;
                x2 = x * x;
                y2 = y * y;
            }

            int c = (n * 255) / MAX_ITERS;
            png_plot(pPng, i, j, c, c, c);

            nTotalIterationsCount  ;
        }
    }

UPDATE: I think you should use nTotalIterationsCount =n; instead of nTotalIterationsCount ;. Most probably that was your intention.

CodePudding user response:

Turns out I didn't declare i and j inside the for loop. Works fine when I move the declaration in there.

  •  Tags:  
  • c
  • Related