0

So, I'm writing a program to compute the Mandelbrot set using pthread.
This is the thread function:

void *partial_compute(void *arg) {
    cout << "enter" << flush;
    Range *range = (Range*)arg;
    Comp z, c;
    for (int i = range->begin; i <= range->end; i++) {
        for (int j = 0; j < y_length; j++) {
            z.set(0.0, 0.0);
            c.set(x_start + (x_end - x_start) * i / x_length, y_start + (y_end - y_start) * j / y_length);
            int k;
            for (k = 0; k < 256; k++) {
                z = z.next(c);
                if (z.length() >= 4.0) {
                    break;
                }
            }
            *(canvas + i * y_length + j) = k;
        }
    }
    pthread_exit(NULL);
}


Which Comp is a class of complex number, and z.next means computing the next Mandelbrot iteration.

Comp Comp::next(Comp c) {
    Comp n(next_real(c), next_imag(c));
    return n;
}
float Comp::next_real(Comp c) {
    return _real * _real - _imag * _imag + c.real();
}
float Comp::next_imag(Comp c) {
    return 2 * _real * _imag + c.imag();
}

I set a pair of clock_t before pthread_create and after pthread_join.
The result of the Mandelbrot set is correct, however, the computing time is always the same despite I increased the number of threads from 1 to 8.
Because the "enter" were printed out at the same time a second before pthread_join, I believe the threads were executed parallelly.
I guess the problem may be that there is the thread-safe function in partial_compute, but I can't find it. (I've try to represent the complex number by the float instead of class)
Is there any mistake I made here? Thank for your help.

Update:
Sorry for the incomplete information.
z.length() means the square of the complex number z.
This is how I split the task. x_length and y_length means the width and the height of the screen.
I split the screen to n part by width, and send the range to the thread to compute.

int partial_length = x_length / num_threads;
for (int i = 0; i < num_threads; i++) {
    range[i].begin = i * partial_length;
    range[i].end = range[i].begin + partial_length - 1;
    pthread_create(&threads[i], NULL, partial_compute, (void *)&range[i]);
}
// wait all the threads finished
for (int i = 0; i < num_threads; i++) {
    pthread_join(threads[i], NULL);
}
Wei-Tsung
  • 297
  • 3
  • 12

2 Answers2

1

I found the problem is the clock()......
The clock() cannot be used to measure the elapsed time when you use pthread,
hence I found gettimeofday(timeval, NULL) can work correctly.

Wei-Tsung
  • 297
  • 3
  • 12
0

Yes, there is a problem with clock() in Pthreads. You can use clock_gettime() with CLOCK_MONOTONIC option, to measure the time correctly in Pthreads. You will also need to link against the POSIX Realtime extensions (-lrt) for this.

Here is an examples:

struct timespec begin, end;
double elapsed;

clock_gettime(CLOCK_MONOTONIC, &begin);

// spawn threads to do work here

clock_gettime(CLOCK_MONOTONIC, &end);

elapsed = end.tv_sec - begin.tv_sec;
elapsed += (end.tv_nsec - begin.tv_nsec) / 1000000000.0;