2017-03-23 3 views
1

J'essaie de générer une image pgm avec une fractale de Buddhabrot, en parallèle, en utilisant pthreads et le modèle maître-esclave. Des tests, je peux voir que le programme démarre le modèle avec le bon mode parallèle, mais il semble être dans une boucle infinie. Le problème est que je ne peux pas voir lequel est le problème. Quelqu'un peut-il me donner une lumière à ce sujet? Je vous remercie.Fractale de Buddhabrot avec pthread

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <math.h> 
#define N_SLAVES 3 

double next = -1; 


int i = 0, nColumns = 2048, nLines = 2048, ite = 600; 
double y, dt = 0.001; 


int completedIterations; 

pthread_mutex_t mutex; 
pthread_cond_t condM; 
pthread_cond_t condE; 

typedef struct { 
    int x; 
    int y; 
} int2; 
typedef struct{ 
    double x; 
    double y; 
} double2; 

int2 coordinatesConversion(double x,double y, int nColumns,int nLines){ 

    int2 ret; 
    int2 retError; 
    retError.x=-1; 
    retError.y=-1; 

    ret.x=round(((2.0+x)/3.5) *((double)(nColumns-1))); 
    ret.y=round(((1.5+y)/3.5) *((double)(nLines-1))); 

    if(ret.x<0 || ret.x>=nColumns) return retError; 
    if(ret.y<0 || ret.y>=nLines) return retError; 

    return ret; 
} 

int printMatrixToFilePGM(float **mat,int tamx, int nLines, char *srcFile){ 

    printf("First\n"); 

    FILE *arq=fopen(srcFile,"w"); 

    int cont, cont2; 
    float min,max; 
    min=mat[0][0]; 
    max=mat[0][0]; 
    for(cont=0;cont<nLines;cont++){ 
     for(cont2=0;cont2<tamx;cont2++){ 
      if(min>mat[cont][cont2]) min=mat[cont][cont2]; 
      if(max<mat[cont][cont2]) max=mat[cont][cont2]; 
     } 
    } 
    max=max*0.35; 
    float delta=max-min; 
    fprintf(arq,"P2 \n"); 
    fprintf(arq,"#something \n"); 
    fprintf(arq,"%d\n%d \n",tamx,nLines); 
    fprintf(arq,"255\n"); 
    for(cont=0;cont<nLines;cont++){ 
     for(cont2=0;cont2<tamx;cont2++){ 
      int valpixel=((mat[cont][cont2]-min)/delta)*255.0f; 
      if(valpixel>255) valpixel=255; 
      fprintf(arq,"%d \n", valpixel); 
     } 
    } 
    fclose(arq); 
} 

float** mallocFloatMatrix(int tamx, int nLines, float defaultValueOfTheElementsAtMatrix){ 

    float **errorCodeReturn=0x0; 
    float **mat; 
    int i,j; 
    int condErrorMalloc=0; 
    mat=malloc(sizeof(float *)*nLines); 
    if(mat==0x0) return errorCodeReturn; 
    for(i=0;i<tamx;i++) 
     mat[i]=malloc(sizeof(float)*tamx); 


    for(i=0;i<tamx;i++){ 
     if(mat[i]==0x0){ 
      condErrorMalloc=1; 
      break; 
     } 
    } 

    if(condErrorMalloc==0){ 
     return mat; 
    } 
    for(i=0;i<nLines;i++){ 
     for(j=0;j<tamx;j++) 
      mat[i][j]=defaultValueOfTheElementsAtMatrix; 
    } 
    for(i=0;i<tamx;i++) 
     if(mat[i]!=0x0) free(mat[i]); 

    free(mat); 

    return errorCodeReturn; 
} 

void freeFloatMatrix(float **mat,int tamx, int nLines){ 
    int i; 
    for(i=0;i<nLines;i++){ 
     if(mat[i]!=0x0) free(mat[i]); 
    } 
    free(mat); 
} 

int iteration(double x,double y, int nColumns,int nLines, int ite,int2 *iterationPath){ 

    int cont;  
    int condInvalidPointer=1; 
    double2 z; 
    z.x=0.0; 
    z.y=0.0; 
    double2 c; 
    c.x=x; 
    c.y=y; 
    double2 zt; 

    for(cont=0;cont<ite;cont++){ 
     zt.x=((z.x*z.x)-(z.y*z.y))+c.x; 
     zt.y=(2.0*(z.x*z.y))+c.y; 
     z=zt; 
     if(((z.x*z.x)+(z.y*z.y))>4.0){ 
      if(cont>100) 
       condInvalidPointer=0; 
      break; 
     } 
     iterationPath[cont]=coordinatesConversion(z.x,z.y,nColumns,nLines); 
    } 
    if(condInvalidPointer) 
     return 0; 

    return cont; 
} 

void *master(void *param){ 
    printf("Second\n"); 
    int size = round(4.0/dt); 
    int i; 
    int progress = 0; 
    for(i = 0; i < size; i++){ 
     next = -2.0+i*dt; 
     pthread_mutex_lock(&mutex); 
     pthread_cond_signal(&condE); 
     pthread_cond_wait(&condM, &mutex); 
     pthread_mutex_unlock(&mutex); 

    //  progress++; 
    //  if(progress%100 ==0)//print at screen information about progrees of the operation 
    //   printf("2 - %lf \n", next); 
    } 
} 


void *slave(void *param){ 
    int size = round(4.0/dt); 
    printf("Third\n"); 
    int k; 
    float **mat = mallocFloatMatrix(nColumns, nLines, 0.0f); 

    if(mat == 0x0) return 0; 


    while(1){ 

     pthread_mutex_lock(&mutex); 
     if(i >= size){ 
      pthread_mutex_unlock(&mutex); 
      pthread_exit(0); 

     } 
     i++; 
     while(next == -1){ 
      pthread_cond_signal(&condM); 
      pthread_cond_wait(&condE, &mutex); 

     } 

     double x = next; 


     next = -1; 

     pthread_cond_signal(&condM); 
     pthread_mutex_unlock(&mutex); 


     for(y=-2.0;y<2.0;y=y+dt){ 
      int2* iterationPath = (int2 *)malloc(sizeof(int2) * ite); 
      if(iterationPath==0x0) return 0x0; 

      completedIterations = iteration(x, y, nColumns, nLines, ite, iterationPath); 



      for(k = 0; k < completedIterations; k++){ 
       if(iterationPath[k].x!=-1 && iterationPath[k].y!=-1)//test if a point z in the iteration k may be normalized to coordinates at matrix mat. 
        mat[iterationPath[k].x][iterationPath[k].y] = mat[iterationPath[k].x][iterationPath[k].y]+1.0f;//increments a point in matrix, this point is pointed by z with z points normalized. 


      } 

      free(iterationPath); 

     } 

    } 
    printMatrixToFilePGM(mat,nColumns,nLines,"saida3.pgm"); 
    freeFloatMatrix(mat,nColumns,nLines); 
} 



int main(void){ 

    printf("Main\n"); 

    int i, j, k; 

    pthread_t master_t; 
    pthread_t slave_t[N_SLAVES]; 

    pthread_create(&master_t, NULL, master, NULL); 

    for(i = 0; i < N_SLAVES; i++) 
     pthread_create(&slave_t[i], NULL, slave, NULL); 

    pthread_exit(0); 

    return 0; 
} 

Répondre

1

Il semble que le problème est que vous assignez -1 comme un chiffre magique à next, ce qui signifie « pas encore initialisé par le maître ». Cependant, il est une possible valeur légitime, parce que vous calculez next comme ceci:

next = -2.0+i*dt; 

Parce que dt est de 0,001, next sera égal à -1 quand i est 1000, et depuis i boucles à 4000 (4.0/dt), il se produira avant la fin de la boucle. Ensuite, vous serez coincé dans une boucle infinie parce que votre thread esclave attend une valeur autre que -1, donc ne définit jamais condM, donc pthread_cond_wait(&condM, &mutex); ne retourne jamais dans le maître, donc i ne s'incrémente jamais.

Changez votre nombre magique de -1 à quelque chose en dehors de la plage de valeurs possibles pour next (par exemple -100), ou utilisez un autre mécanisme.