0

I am working on a project to rewrite a sequential C-code algorithm for creating a mandelbrot set into a parallel one using pthreads. I've gone up against a wall so to speak, as my version simply outputs a more or less black picture (and nothing to what the original program results into), and I can't really see where I'm going wrong. Simply put, I could use a second pair of eyes on this one.

Here is the sequential code snippet that matters:

void mandelbrot(float width, float height, unsigned int *pixmap)
{
int i, j;
float xmin = -1.6f;
float xmax = 1.6f;
float ymin = -1.6f;
float ymax = 1.6f;
for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
        float b = xmin + j * (xmax - xmin) / width;
        float a = ymin + i * (ymax - ymin) / height;
        float sx = 0.0f;
        float sy = 0.0f;
        int ii = 0;
        while (sx + sy <= 64.0f) {
            float xn = sx * sx - sy * sy + b;
            float yn = 2 * sx * sy + a;
            sx = xn;
            sy = yn;
            ii++;
            if (ii == 1500) {
                break;
            }
        }
        if (ii == 1500) {
            pixmap[j+i*(int)width] = 0;
        }
        else {
            int c = (int)((ii / 32.0f) * 256.0f);
            pixmap[j + i *(int)width] = pal[c%256];
        }
    }
}


}

Here is my sequential version of the code:

void* Mandel(void* threadId) {
    int x = *(int*)threadId;
    float xmin = -1.6f;
    float xmax = 1.6f;
    float ymin = -1.6f;
    float ymax = 1.6f;

    float b = xmin + x * (xmax - xmin) / WIDTH;
    for (int y = 0; y < 1024; y++)
    {
        float a = ymin + y * (ymax - ymin) / WIDTH;
        float sx = 0.0f;
        float sy = 0.0f;
        int ii = 0;
        while (sx + sy <= 64.0f) {
            float xn = sx * sx - sy * sy + b;
            float yn = 2 * sx * sy + a;
            sx = xn;
            sy = yn;
            ii++;
            if (ii == 1500) {
                break;
            }
        }
        if (ii == 1500) {
            pixmap[x+y*(int)WIDTH] = 0;
        }
        else {
            int c = (int)((ii / 32.0f) * 256.0f);
            pixmap[x + y *(int)WIDTH] = pal[c%256];
        }
    }
}

Explanation of my thought process: I create 1024 threads in the main function, and then call on the function above with each thread. They're supposed to a column each (since the x is a constant between 0 and 1023, while the y value changes from 0 to 1023 within the function). As you can see, most of the mathematical meat in the function itself is the same in both the sequential and my parallel versions of the code. Because of this, I think the problem comes from how I'm stepping through the array, but I cannot see the problem with my own eyes. Regardless, the value that ii eventually receives is used to calculate c, which in turn is used to decide the color value that's to be saved in the corresponding position in pixmap. (pal is basically just a large array filled with color values).

This function is the only piece of the code that I've actually touched to any major degree. The only difference in the main function is that I've created threads in it with the instruction to carry out the function Mandel.

I assume that anyone willing to help will want more information, and please let me know of any improvements to this post in case I have posted too little information.

Jens Lomander
  • 111
  • 2
  • 10
  • How are you passing in the threadId when you start the threads? Since you seem to be using a pointer, you need to keep the actual value around after calling pthread_create(). If you for instance use the same variable, and just increment it after creating each thread, the individual threads will probably not get the correct values, as the location pointed to by threadId will have changed before the value is read in... – sonicwave Jan 29 '17 at 16:00
  • I have solved it myself, I will post an update answer to it. – Jens Lomander Jan 29 '17 at 16:15
  • But yes you did hit the nail right on the head there :P – Jens Lomander Jan 29 '17 at 16:23

1 Answers1

0

I found an answer shortly after posting this code. Silly me.

Anywho, the problem wasn't stepping through the array within the function, but actually how I created the threads.

This is how it looked in main when the problem occurred:

for(int k = 0; k < 1024; k++) {
    pthread_create(&threads[k], NULL, (void*)Mandel, (void*) k);
}

The problem with doing it this way was that the loop continued, changing the value of k for the next thread, meaning that the last thread that we just created suddenly got an erronous value for k. This was solved by using an int array which saves the values of k as we go through each k value and create each thread, like shown below:

int id[1024];
for(int k = 0; k < 1024; k++) {
    pthread_create(&threads[k], NULL, (void*)Mandel, (void*)(id+k));
}

I would like to point towards the post in the following link, for helping me answer this problem: Pass integer value through pthread_create

Just goes to show that you can often find the answers you're looking for if you search long enough, for the most of the time.

Community
  • 1
  • 1
Jens Lomander
  • 111
  • 2
  • 10