2013-04-23 2 views
0

У меня есть следующий код Pthreads о вычислении и создании изображения набора Мандельброта. Мой код в C работает отлично, и он хорошо печатает полученную картинку. Дело в том, что, используя приведенный ниже код, я могу скомпилировать код и выполнить его. Впоследствии, если я попытаюсь просмотреть полученный файл .ppm в Gimp, он просто не сможет его открыть. Думаю, я делаю что-то неправильно в своем коде. Если бы кто-то мог мне помочь, я был бы рад.Как исправить мой код Pthreads о наборе Мандельброта?

// mandpthread.c 
// to compile: gcc mandpthread.c -o mandpthread -lm -lrt -lpthread 
// usage: ./mandpthread <no_of_iterations> <no_of_threads> > output.ppm 

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <time.h> 
#include <assert.h> 
#include <pthread.h> 

typedef struct { 
    int r, g, b; 
} rgb; 

int NITERATIONS, NTHREADS; 
rgb **m; 

void color(rgb **m, int x, int y, int red, int green, int blue) 
{ 
    m[y][x].r = red; 
    m[y][x].g = green; 
    m[y][x].b = blue; 
} 

void mandelbrot(int tid) 
{ 
    int w = 600, h = 400, x, y; 
    // each iteration, it calculates: newz = oldz*oldz + p, 
    // where p is the current pixel, and oldz stars at the origin 
    double pr, pi;     // real and imaginary part of the pixel p 
    double newRe, newIm, oldRe, oldIm; // real and imaginary parts of new and old z 
    double zoom = 1, moveX = -0.5, moveY = 0; // you can change these to zoom and change position 

    int start = tid * NITERATIONS/NTHREADS; 
    int end = (tid+1) * (NITERATIONS/NTHREADS) - 1; 

    //loop through every pixel 
    for(y = 0; y < h; y++) { 
     for(x = 0; x < w; x++) { 
      // calculate the initial real and imaginary part of z, 
      // based on the pixel location and zoom and position values 
      pr = 1.5 * (x - w/2)/(0.5 * zoom * w) + moveX; 
       pi = (y - h/2)/(0.5 * zoom * h) + moveY; 
       newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0 
       // i will represent the number of iterations 
       int i; 
       // start the iteration process 
       for(i = start; i <= end; i++) { 
         // remember value of previous iteration 
         oldRe = newRe; 
         oldIm = newIm; 
         // the actual iteration, the real and imaginary part are calculated 
         newRe = oldRe * oldRe - oldIm * oldIm + pr; 
         newIm = 2 * oldRe * oldIm + pi; 
         // if the point is outside the circle with radius 2: stop 
         if((newRe * newRe + newIm * newIm) > 4) break; 
       } 

       if(i == NITERATIONS) 
       color(m, x, y, 0, 0, 0); // black 
      else 
      { 
       // normalized iteration count method for proper coloring 
       double z = sqrt(newRe * newRe + newIm * newIm); 
       int brightness = 256. * log2(1.75 + i - log2(log2(z)))/log2((double)NITERATIONS); 
       color(m, x, y, brightness, brightness, 255); 
      } 

      } 
    } 

} 

// worker function which will be passed to pthread_create function 
void *worker(void *arg) 
{ 
    int tid = (int)arg; 
    mandelbrot(tid); 
} 


int main(int argc, char *argv[]) 
{ 
    pthread_t* threads; 
    int i, j, rc; 

    if(argc != 3) 
    { 
     printf("Usage: %s <no_of_iterations> <no_of_threads> > output.ppm\n", argv[0]); 
     exit(1); 
    } 

    NITERATIONS = atoi(argv[1]); 
    NTHREADS = atoi(argv[2]); 
    threads = (pthread_t*)malloc(NTHREADS * sizeof(pthread_t)); 

    m = malloc(400 * sizeof(rgb *)); 
    for(i = 0; i < 400; i++) 
     m[i] = malloc(600 * sizeof(rgb)); 

    // declaring the needed variables for calculating the running time 
    struct timespec begin, end; 
    double time_spent; 

    // starting the run time 
    clock_gettime(CLOCK_MONOTONIC, &begin); 

    printf("P6\n# AUTHOR: ET\n"); 
    printf("%d %d\n255\n",600,400); 

    for(i = 0; i < NTHREADS; i++) { 
     rc = pthread_create(&threads[i], NULL, worker, (void *)i); 
     assert(rc == 0); // checking whether thread creating was successfull 
    } 

    for(i = 0; i < NTHREADS; i++) { 
     rc = pthread_join(threads[i], NULL); 
     assert(rc == 0); // checking whether thread join was successfull 
    } 

    // printing to file 
    for(i = 0; i < 400; i++) { 
     for(j = 0; j < 600; j++) { 
      fputc((char)m[i][j].r, stdout); 
      fputc((char)m[i][j].g, stdout); 
      fputc((char)m[i][j].b, stdout); 
     } 
    } 

    // ending the run time 
    clock_gettime(CLOCK_MONOTONIC, &end); 

    // calculating time spent during the calculation and printing it 
    time_spent = end.tv_sec - begin.tv_sec; 
    time_spent += (end.tv_nsec - begin.tv_nsec)/1000000000.0; 
    fprintf(stderr, "Elapsed time: %.2lf seconds.\n", time_spent); 

    for(i = 0; i < 400; i++) 
     free(m[i]); 
    free(m); 

    free(threads); 

    return 0; 
} 
+3

Какие утверждения фактически распечатать данные пикселя? – alk

+0

Этот код работает для меня с 1 нитью (100 итераций) – parkydr

ответ

1

Самая новая версия вашего кода работает для меня с 100 итерациями и 1 нитью.

enter image description here

Выполнение двух потоков не удается, потому что файл имеет 2 ппм заголовки одного из каждого потока.

Если я удалю один из заголовков, изображение загрузится, но цвета отключены, и на изображении появится сбой.

enter image description here

+0

Ops, извините, я забыл добавить эту часть. Теперь я редактировал и добавлял в свой исходный код часть для печати в файл. Я также попытался использовать ваш код для печати, но все же теперь удача. – 2013-04-23 16:22:08

+0

Вы изменили P6 на P3? Это делает его ASCII в соответствии с gimp или P2 для двоичного кода. – parkydr

+0

Ответ отредактирован в соответствии с последним кодом – parkydr