0

Je suis en train de créer un code alternatif qui triera un tableau avec plusieurs threads, donc je dois utiliser des barrières pour synchroniser les menacesPthread-barrières en C

void sort(struct ThreadArguments* args){ 
     struct ThreadArguments* the_args= (struct ThreadArguments*)args; 
     printf("thread %d started \n", the_args->id); 
     fflush(stdout); 
     pthread_barrier_wait (the_args->barrier); 
     printf("thread %d finished the iteration \n", the_args->id); 
     fflush(stdout); 
} 

Ma structure d'arguments ressemble que

struct ThreadArguments { 
unsigned int id; 
int* array; 
pthread_barrier_t* barrier; 
} 

Et voilà comment j'initialiser les obstacles

pthread_barrier_init (&barrier, NULL, 4); 

Je pense à faire une itération de sorti méthode ng puis attendez toutes les discussions se terminent à la barrière, puis procéder, mais ce qui est fait est

thread 0 started 
thread 1 started 
thread 2 started 
thread 3 started 

puis se coincer. Quel pourrait être le problème? EDIT: code complet

#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/time.h> 
#include <string.h> 
#include <pthread.h> 

#define MAXFILENAME 64 
#define TIMESTEP 200000 
#define MAXTHREADS 2046 





//Thread arguemnt struct 
struct ThreadData { 
    unsigned int id; //thread's id 
    int start; //starting index of the workers's part 
    int step; //step between each consecutive cells 
    int cells; //how many cells is worker respnsible for 
    pthread_barrier_t* enter_barrier; //this barrier synchornizes threads to wait till the copy of the array is created 
    pthread_barrier_t* exit_barrier; //this barrier is used to wait till all threads finished updating 
    pthread_barrier_t* print_barrier; 
    int print; 
    int iter; 
    int rows; //row dimensions 
    int columns; //column dimensions 
    char* array; //pointer to the original array 
    char* working_array; //pointer to the dublicate array used during each step 
}; 



int readIn(int *rows, int *columns, int *iter, int *num_cells, FILE *fp); 
char *initialize(int rows, int columns, int num_cells, FILE *fp); 
void printBoard(int rows, int columns, char *cells, int num_cells); 
int checkNeighb(int rows, int columns, char *cells, int num_cells, int target); 
void evolve(struct ThreadData* args); 
void printUsage(int code); 
void initializeThreads(int part_type, int num_iter, int print_opt, struct ThreadData* data, int num_threads, int num_rows, int num_cols, char* cells); 
int processAgrs(int argc, char **argv, char **filename, int* print_opt, int* num_threads, int* part_type, int* print_per_thread); 



// Main method 
int main(int argc, char *argv[]) { 

    int num_rows; //number of rows on the board 
    int num_cols; 
    int num_iter; 
    int num_cells; 
    int print_opt; 
    int num_threads; 
    int part_type; 
    int print_per_thread; 
    int i, ret; 

    char *filename = malloc(MAXFILENAME*sizeof(char)); 
    ret = processAgrs(argc, argv, &filename, &print_opt, &num_threads, &part_type, &print_per_thread); 
    if(ret == -1) 
    { 
     exit(1); 
    } 

    FILE *fp = fopen (filename, "rb");  //openning file 

    if(fp == NULL) 
    { 
     perror("Error openning file"); 
     exit(1); 
    } 

    if(readIn(&num_rows, &num_cols, &num_iter, &num_cells, fp) == -1) //check that everything was successful 
    { 
     printf("Error reading from file \n"); 
     exit(1); 
    } 

    char* cells = initialize(num_rows, num_cols, num_cells, fp); 
    if(cells == NULL) 
    { 
     printf("Error initializing board! \n"); 
     exit(1); 
    } 
    struct ThreadData *data = malloc(num_threads * sizeof(struct ThreadData)); 
    initializeThreads(part_type, num_iter, print_opt, data, num_threads, num_rows, num_cols, cells); 
    struct timeval start_time, end_time; 
    double elapsed = 0; 

    if(gettimeofday(&start_time, NULL) == -1) 
    { 
     printf("Error getting time \n"); 
     elapsed = -1; 
    } 

    pthread_t *thread = malloc(num_threads*sizeof(pthread_t)); 
    printf("Start creating threads"); 
    fflush(stdout); 
    // Launching Threads 
    for (i=0; i<num_threads; i++) { 
     printf("Create threads %d \n", i); 
     fflush(stdout); 
     ret = pthread_create(&thread[i], NULL,(void *) &evolve,(void *) &data[i]); 
     if(ret != 0) 
     { 
      printf("Error creating thread"); 
     } 
    } 

    // Waiting for Threads to Finish 
    for (i=0; i<num_threads; i++) { 
     pthread_join(thread[i], NULL); 
    } 

    if(gettimeofday(&end_time, NULL) == -1 || elapsed == -1) 
    { 
     printf("Time was not calulcated due to error! \n"); 
    } 
    else{ //print ellapsed time 
     elapsed = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec)/1000000.0; 
     printf("total time for %d iterations of %dx%d world is %.6f secs \n",num_iter, num_rows, num_cols, elapsed); 
    } 

    free(cells); 
    free(filename); 
    return 0; 
} 

void initializeThreads(int part_type, int num_iter, int print_opt, struct ThreadData* data, int num_threads, int num_rows, int num_cols, char* cells) 
{ 
    int i, prev; 
    int num_of_extras; //extras is thread that gets one more line/column 
    pthread_barrier_t enter_barrier; //this barrier synchornizes threads to wait 
    //till the copy of the array is created 
    pthread_barrier_t exit_barrier;//this barrier waits for all threads to finish updating cells 
    pthread_barrier_t print_barrier; 


    pthread_barrier_init (&enter_barrier, NULL, num_threads); //initialize barrier for copying array 
    pthread_barrier_init (&exit_barrier, NULL, num_threads); //initialize exit barrier 
    pthread_barrier_init (&print_barrier, NULL, num_threads); 

    char *copy_cells = malloc((num_rows * num_cols) * sizeof(char)); 
     if(copy_cells == NULL)  //Checking malloc 
     { 
       perror("Error mallocing"); 
       free(copy_cells); 
       return; 
     } 

    for (i = 0; i < num_threads; i++) 
{ 
    data[i].enter_barrier = &enter_barrier; 
    data[i].exit_barrier = &exit_barrier; 
    data[i].print_barrier = &print_barrier; 
    data[i].iter = num_iter; 
    data[i].rows = num_rows; 
    data[i].columns = num_cols; 
    data[i].working_array = copy_cells; 
    data[i].array = cells; 
    data[i].print = print_opt; 
}  
    if(part_type == 0) //if row-wise paritioning 
    { 

     int lines_per_thread = num_rows/num_threads; 
     num_of_extras = num_rows % num_threads; 
     prev = 0; 
     for (i = 0; i < num_threads; i++) 
     { 
      data[i].id = i; 
      data[i].start = prev; 
      if(num_of_extras == 0) 
      { 
       data[i].cells = lines_per_thread * num_cols; 
       prev+=data[i].cells; 
      } 
      else{ 

       data[i].cells = (lines_per_thread + 1) * num_cols; 
       prev+=data[i].cells; 
         num_of_extras--; 
      } 
     data[i].step = 1; 
     } 
    } 
    else{  //column-wise patitioning 
     int columns_per_thread = num_cols/num_threads; 
     num_of_extras = num_cols % num_threads; 
     prev = 0; 
     for (i = 0; i < num_threads; i++) 
     { 
      data[i].id = i; 
      data[i].start = prev; 
      if(num_of_extras == 0) 
      { 
       data[i].cells = columns_per_thread * num_rows; 
      } 
      else{ 
       data[i].cells = (columns_per_thread + 1) * num_rows; 
       num_of_extras--; 
      } 
      data[i].step = num_cols; 
      prev++; 
     } 
    } 

} 



int processAgrs(int argc, char **argv, char **filename, int* print_opt, int* num_threads, int* part_type, int* print_per_thread) 
{ 
    if (argc < 6) {  //reading arguments from command line 
     printf("Too few arguments!"); 
     printUsage(1); 
     return -1; 
    } 
    else if(argc > 6) 
    { 
     printf("Too many arguments!"); 
     printUsage(1); 
     return -1; 
    } 
    else 
    { 
     strcpy(*filename, argv[1]); 


     *print_opt = strtol(argv[2], NULL, 10); //using strtol() to convert string to int 
     if(*print_opt < 0 || *print_opt > 1) 
     { 
      printf("Illiegal prinitng option! \n 1 - Print \n 0 - Don't print \n"); 
      printUsage(1); 
      return -1; 
     } 



     *num_threads = strtol(argv[3], NULL, 10); //using strtol() to convert string to int 
     if(*num_threads < 1 || *num_threads > MAXTHREADS) 
     { 
      if(*num_threads == -1) 
      { 
       printf("Having %d thread is not allowed! \n",*num_threads); //for correct grammar print "thread" if user entered -1 
      } 
      else{ 
       printf("Having %d threads is not allowed! \n",*num_threads); 
      } 
      return -1; 
     } 



     *part_type = strtol(argv[4], NULL, 10); //using strtol() to convert string to int 
     if(*part_type < 0 || *part_type > 1) 
     { 
      printf("Illiegal partitioning option! \n"); 
      printUsage(2); 
      return -1; 
     } 




     *print_per_thread = strtol(argv[5], NULL, 10); //using strtol() to convert string to int 
     if(*print_per_thread < 0 || *print_per_thread > 1) 
     { 
      printf("Illiegal prinitng option! \n 1 - Print \n 0 - Don't print \n"); 
      printUsage(1); 
      return -1; 
     } 

     return 0; 
    } 
} 
/* @biref this method prints usage infromation for a specified case 
* @arg code ths arguemnts sepcifies which help message should be printed, general usage is argument 0 
*/ 
void printUsage(int code) 
{ 
    switch(code) 
    { 
     case 0: 
      printf("Usage: \n"); 
      printf(" ./gol print-option number of threads partitioning-type  print-per-thread\n"); 
      printf(" Example: \n"); 
      printf(" ./gol file1.txt 0 8 0 1 \n"); 
      printf(" run with config values read from file1.txt, do not print the board after\n each round, create 8 threads, use row-wise partitioning, print per-thread\npartitioning details"); 
      break; 
     case 1: 
      printf("Print options are 1 or 0.\n"); 
      printf(" 1 for print \n 0 for do not print"); 
      break; 
     case 2: 
      printf("Partitioning orptions are 1 or 0.\n"); 
      printf(" 0 for row-wise partitioning \n 1 for column-wise partitioning"); 
      break; 
     default : 
      break; 
    } 
} 




/* @biref this method does one step of the game by first calling checkNeighb() and then choosing apporopriate action 
* @param rows - number of rows of the field 
* @param columns - number of comuns of the filed 
* @param cells - pointer to the 1D array representing our field 
* @param num_cells - total number of cells 
*/ 
void evolve(struct ThreadData* args) 
{ 
    ////////////// 

    struct ThreadData* the_args= (struct ThreadData*)args; 
    printf("thread %d started", the_args->id); 
    fflush(stdout); 

/* int i; 
    int neighb; 
    int start = the_args->start; 
    int step = the_args->step; 
    int num_cells = the_args->cells; 
    int end; 
    int total_cells = (the_args->columns * the_args->rows); 

if(the_args->id == 0) //print the initial state of the board 
    { system("clear"); 
     if(the_args->print == 1) 
     { 
      printf("Time step: %d \n\n", TIMESTEP); 
      printBoard(the_args->rows, the_args->columns , the_args->array, total_cells); 
      usleep(TIMESTEP); 
     } 
    } 

    ///Main loop. Each itteration of the loop is a one round of game. 
    for(i = 0; i < the_args->iter; i++) 
    { 
     //DEBUG 
     end = (start + (num_cells * step)); 
     for(i = start; i < end ; i+=step) //copy cell state to the array 
     { 
      the_args->working_array[i] = the_args->array[i]; 
     } 
     //barrier 
     printf("at the barrier, %d!", the_args->id); 
       fflush(stdout); 
*/ 
     pthread_barrier_wait (the_args->enter_barrier); 
/* 
     for(i = start; i < end; i+=step) 
     { 
      neighb = checkNeighb(the_args->rows, the_args->columns, the_args->array, num_cells, i); //get number of neighbors 
      if((neighb < 2 || neighb > 3) && the_args->array[i] == 1) 
      { 
       the_args->working_array[i] = 0; 
      }else if(the_args->array[i] == 0 && neighb == 3) 
      { 
       the_args->working_array[i] = 1; 
      } 
     } 


     //barrier 
     pthread_barrier_wait (the_args->exit_barrier); 
     for(i = start; i < end; i+=step) 
     { 
      the_args->array[i] = the_args->working_array[i]; 
     } 
     //barrier 
     pthread_barrier_wait (the_args->print_barrier); 
     if(the_args->id == 0) //first (0th) thread should print the board 
     { system("clear"); 
      printf("at the second print \n"); 
      if(the_args->print == 1) 
      { 
       printf("Time step: %d \n\n", TIMESTEP); 
       printBoard(the_args->rows, the_args->columns , the_args->array, total_cells); 
       usleep(TIMESTEP); 
      } 
     } 

    } 
*/ 
} 
/* 
* @biref this read in main parameters from text file 
* @param num_rows - pointer to the number of rows of the field 
* @param num_columns - pointer to the number of comuns of the filed 
* @param num_iter - pointer to the number of iterations 
* @param num_cells - pointer to the total number of cells 
* @param fp - pointer to the open file 
* @return returns 0 on success and -1 on error 
*/ 
int readIn(int *num_rows, int *num_columns, int *num_iter, int *num_cells, FILE *fp) 
{ 

    if(fscanf(fp, "%d", num_rows) < 1) 
     return -1; 

    if(fscanf(fp, "%d", num_columns) < 1) 
     return -1; 

    if(fscanf(fp, "%d", num_iter) < 1) 
     return -1; 

    if(fscanf(fp, "%d", num_cells) < 1) 
     return -1; 


    return 0; 
} 

/* @biref this method creates a 1D array and fills it with the corrct data 
* @param rows - number of rows of the field 
* @param columns - number of comuns of the filed 
* @param - which way should the array be asigned by columns or by rows (used to optimize perfomance in a column partitioning) 
* @param num_cells - total number of cells 
* @param fp - pointer to the open file 
* @return - returns pointer to the 1D array 
*/ 
char* initialize(int rows, int columns, int num_cells, FILE *fp) 
{ 
    int k = 0; 
    int i, j, index; 
    int length = (rows * columns); //total number of elements in the array (area of the board) 
    char *cells = calloc((rows * columns), sizeof(char)); 
    if(cells == NULL) //checking malloc 
    { 
     perror("Error mallocing"); 
     free(cells); 
     return NULL; 
    } 

    while(k < num_cells) 
    { 
     if(fscanf(fp, "%d %d",&i ,&j) == 2) 
     { 
      index = ((i * columns) + j); 
      if(index < length) 
      { 
       cells[index] = 1; 
      } 
      else{  //in case entries are outside of the board 
       printf("Invalid entry: %d %d is outside the boundaries", i, j); 
      } 
      k++; 
     } 
     else{ 
      printf("Error reading i j coordinate pair %d", k); 
     } 
    } 
    return cells; 
} 

/* 
* @biref this method counts number of naeighbors of the cell with a given index in a 1D representation 
* @param rows - the number of rows of the field 
* @param columns - the number of comuns of the filed 
* @param cells - pointer to the 1D arrray 
* @param num_cells - the total number of cells 
* @param target - index of the cell 
* @return returns number of neighbors 
*/ 
int checkNeighb(int rows, int columns, char *cells, int num_cells, int target) 
{ 
    int count = 0; 

    if((target % columns) == 0) //left edge 
    { 
     if(target == 0) //top left corner 
     { 
      if(cells[(rows*columns) -1 ] == 1) //up-left 1 
      { 
       count++; 
      } 
      if(cells[((rows - 1) * columns)] == 1) //up 2 
      { 
       count ++; 
      } 
      if(cells[((rows - 1) * columns)+ 1] == 1) //up-right 3 
      { 
       count ++; 
      } 

     } 
     else{ //if not top left corner 
      if(cells[target - 1] == 1) //up-left 1.1 
      { 
       count++; 
      } 
      if(cells[(target - columns)] == 1) //up 2.1 
      { 
       count ++; 
      } 
      if(cells[(target - columns) + 1] == 1) //up-right 3.1 
      { 
       count++; 
      } 
     } 

     if(target == (rows - 1) * columns) //bottom left corner 
     { 
      if(cells[(columns)-1 ] == 1) //down-left 4 
      { 
       count++; 
      } 
      if(cells[0] == 1) //down 5 
      { 
       count ++; 
      } 
      if(cells[1] == 1) //up-right 6 
      { 
       count ++; 
      } 
     } 
     else{ 
      //if not bottom left corner 
      if(cells[ target + (2 * columns) - 1 ] == 1) //down-left 4.1 
      { 
       count++; 
      } 
      if(cells[ target + columns ] == 1) //down 5.1 
      { 
       count ++; 
      } 
      if(cells[ (target + columns) + 1] == 1) //down-right 6.1 
      { 
       count ++; 
      } 
     } 


     if(cells[ target + 1] == 1) //right 7 
     { 
      count++; 
     } 
     if(cells[(target + columns) - 1] == 1) //left 8 
     { 
      count++; 
     } 
    } 
    else if(((target +1) % columns) == 0) //right edge 
    { 

     if(target == (columns - 1)) //top right corner 
     { 
      if(cells[(rows * columns) - 2 ] == 1) //up-left 1 
      { 
       count++; 
      } 
      if(cells[(rows * columns) - 1] == 1) //up 2 
      { 
       count ++; 
      } 
      if(cells[((rows-1) * columns)] == 1) //up-right 3 
      { 
       count ++; 
      } 

     } 
     else{ //if not top right corner 
      if(cells[(target - columns) - 1] == 1) //up-left 1.1 
      { 
       count++; 
      } 
      if(cells[(target - columns)] == 1) //up 2.1 
      { 
       count ++; 
      } 
      if(cells[(target - (2 * columns)) + 1] == 1) //up-right 3.1 
      { 
       count++; 
      } 
     } 

     if(target == ((rows * columns) -1)) //bottom right corner 
     { 
      if(cells[columns - 2 ] == 1) //down-left 4 
      { 
       count++; 
      } 
      if(cells[ columns - 1 ] == 1) //down 5 
      { 
       count ++; 
      } 
      if(cells[0] == 1) //down-right 6 
      { 
       count ++; 
      } 
     } 
     else{ 
      //if not bottom right corner 
      if(cells[ (target + columns) - 1 ] == 1) //down-left 4.1 
      { 
       count++; 
      } 
      if(cells[ target + columns ] == 1) //down 5.1 
      { 
       count ++; 
      } 
      if(cells[ target + 1 ] == 1) //down-right 6.1 
      { 
       count ++; 
      } 
     } 
     if(cells[(target - columns) + 1] == 1) //right 7 
     { 
      count++; 
     } 
     if(cells[target - 1 ] == 1) //left 8 
     { 
      count++; 
     } 
    } 
    else if(target > ((rows-1)*columns)) //bottom edge not corner 
    { 
     if(cells[target - 1] == 1) //left 1 
     { 
      count++; 
     } 
     if(cells[target + 1] == 1) //right 2 
     { 
      count++; 
     } 
     if(cells[target - columns] == 1) //up 3 
     { 
      count++; 
     } 
     if(cells[(target - columns) - 1] == 1) //up -left 4 
     { 
      count++; 
     } 
     if(cells[(target - columns) + 1] == 1) //up -right 5 
     { 
      count++; 
     } 
     if(cells[target % columns] == 1) //down 5 
     { 
      count++; 
     } 
     if(cells[(target % columns) + 1] == 1) //down -right 7 
     { 
      count++; 
     } 
     if(cells[(target % columns) + -1] == 1) //down -left 8 
     { 
      count++; 
     } 

    } 
    else if(target < columns) //top edge not corners 
    { 
     if(cells[target - 1] == 1) //left 1 
     { 
      count++; 
     } 
     if(cells[target + 1] == 1) //right 2 
     { 
      count++; 
     } 

     if(cells[target + ((rows-1) * columns)] == 1) //up 3 
     { 
      count++; 
     } 
     if(cells[(target + ((rows-1) * columns)) - 1] == 1) //up -left 4 
     { 
      count++; 
     } 
     if(cells[(target + ((rows-1) * columns)) + 1] == 1) //up - right 5 
     { 
      count++; 
     } 
     if(cells[target + columns] == 1) //down 5 
     { 
      count++; 
     } 
     if(cells[(target + columns) + 1] == 1) //down -right 7 
     { 
      count++; 
     } 
     if(cells[(target + columns) + -1] == 1) //down -left 8 
     { 
      count++; 
     } 

    } 
    else{ //middle 


     if(cells[target - 1] == 1) //left 1 
     { 
      count++; 
     } 
     if(cells[target + 1] == 1) //right 2 
     { 
      count++; 
     } 

     if(cells[target - columns] == 1) //up 3 
     { 

      count++; 
     } 
     if(cells[(target - columns) - 1] == 1) //up -left 4 
     { 
      count++; 
     } 
     if(cells[(target - columns) + 1] == 1) //up -right 5 
     { 
      count++; 
     } 
     if(cells[target + columns] == 1) //down 5 
     { 
      count++; 
     } 
     if(cells[(target + columns) + 1] == 1) //down -right 7 
     { 
      count++; 
     } 
     if(cells[(target + columns) + -1] == 1) //down -left 8 
     { 
      count++; 
     } 
    } 
    return count; 
} 

// @biref this method prints out the board 
void printBoard(int rows, int columns, char *cells, int num_cells) 
{ 
    int i, j; 

    for(i = 0; i < rows; i++) 
    {  
     for(j=0; j < columns; j++) 
     { 
      if(cells[ (i * columns) + j ] == 1) 
      { 
       printf("@ "); //if 1 
      } 
      else{ 
       printf("- "); //if 0 
      } 
     } 
     printf("\n"); 
    } 
    printf("\n"); 
    return; 
} 
+0

Pour être complet, veuillez montrer comment 'the_args' est initialisé avant d'être passé à' pthread_create'. Suggère aussi un 'printf' après le tri et avant que la barrière n'attende. Vous n'avez pas montré le code de tri, donc je crois qu'il n'est pas coincé à l'intérieur, mais qu'il serait bon de l'indiquer/de le montrer explicitement. – kaylum

+0

J'ai complètement commenté toute la partie de tri et il fait toujours la même chose –

+1

Le code que vous avez fourni semble généralement bien ainsi, comme @kaylum suggéré, si vous souhaitez plus d'aide pouvez-vous s'il vous plaît fournir le code entourant 'pthread_barrier_init' et quels appels 'pthread_create'? Idéalement, fournir un programme autonome que nous pouvons compiler et exécuter. Pour des points supplémentaires, dites-nous quel système d'exploitation vous utilisez. – Turn

Répondre

0

La barrière

pthread_barrier_t enter_barrier; //this barrier synchornizes threads to wait 

est un objet local dans la fonction initializeThreads(). La durée de vie de cet objet se termine lorsque initializeThreads() se termine, ce qui précède le démarrage des threads et appelle pthread_barrier_wait (the_args->enter_barrier). Il n'est pas étonnant que l'attente d'une barrière inexistante ne fonctionne pas.