2013-04-23 2 views
0

Mandelbrot 세트의 그림을 계산하고 생성하는 데 필요한 다음 Pthreads 코드가 있습니다. C의 제 코드는 잘 작동하며 결과 그림을 멋지게 인쇄합니다. 핵심은 아래 코드를 사용하여 코드를 컴파일하고 실행할 수 있다는 것입니다. 그 다음에 Gimp에서 결과 .ppm 파일을 보려고하면 단순히 열 수 없습니다. 내 코드에서 뭔가 잘못하고있는 것 같아. 누군가가 나를 도울 수 있다면 기쁠 것입니다.Mandelbrot에 대한 내 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 회의 스레드로 작동합니다. ppm 단위 파일이 헤더 각 스레드에서 하나를 가지고 있기 때문에 두 개의 스레드를하는

enter image description here

는 실패합니다.

머리글 중 하나를 삭제하면 이미지가로드되지만 색상이 꺼지고 이미지에 결함이 있습니다.

enter image description here

+0

작전, 죄송합니다, 그 부분을 추가하는 것을 잊어 버렸습니다. 이제 편집하여 원래 코드에 파일 인쇄 부분을 추가했습니다. 인쇄를 위해 코드를 사용해 보았지만 여전히 운이 좋습니다. –

+0

P6을 P3으로 변경 했습니까? 그것은 gimp에 따라 ASCII가되고, 바이너리는 P2가됩니다. – parkydr

+0

답변은 최신 코드 – parkydr