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:
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.