2013-02-08 3 views
1

Что нужно сделать, чтобы выполнить следующий код, чтобы вычислить Матричное умножение A и B для получения матрицы C. Он использует потоки nXn для вычисления каждой записи C независимо. Таким образом, код работает на Cygwin, но не на Linux. Я продолжаю получать сегмент по умолчанию с вызовами Pthread_join.Pthread_join() Причинение ошибки по умолчанию сегмента

#define _REENTRANT // Make sure the library functions are MT (muti-thread) safe 
#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <time.h> 
#include <string.h> 

#define BUFFER_SIZE 512 

// Declare a structure data type that will be used to pass arguments to the worker threads 
typedef struct args_for_thread_t{ 
     int *rowA; 
     int rowIdx; 
     int *columnB; 
     int columnIdx; 
     int **matrixC; 

} ARGS_FOR_THREAD; 
/* Global Variables */ 
int numRows,numColumns; 

/*Function Prototype*/ 
void *computeC(void *this_arg); 
void printMatrix(int** matrix,int numRows,int numColumns); 

int main(void){ 
    const char filename[] = "input_data.txt"; 
    FILE *file = fopen(filename,"r"); 
    char *delims = " "; 
    int **matrixA,**matrixB,**matrixC; 
    int flagB = 0; //Indicate wether the program should process matrixB 
    int i,j; 

    if (file){ 
     char line[BUFFER_SIZE]; 
     int rowIdx = 0; 
     while (fgets(line,sizeof(line), file)){ 
      char substr[BUFFER_SIZE], *result; 
      //fputs(line,stdout); 
      result = strtok(line, delims); 
      int columnIdx = 0; 

      //Once we reach a line break, we start the processing of matrix B 
      if (!strcmp(line,"\n")){ 
       flagB = 1; 
       rowIdx = 0; //Reset the rowIdx 
       continue; //Skip the new line, and start to read data into matrix B 
      } 
      while (result != NULL){ 
       if (!strcmp(result,"ROWS")){ //To retrieve the number of rows 
        result = strtok(NULL,delims); 
        numRows = atoi(result); 
        matrixA = (int **) malloc(numRows*sizeof(int*)); 
        matrixB = (int **) malloc(numRows*sizeof(int*)); 
        matrixC = (int **) malloc(numRows*sizeof(int*)); 
        rowIdx = -1; 
        result = strtok(NULL,delims); 
       } 
       else if (!strcmp(result,"COLUMNS")){//To retrieve the number of Columns 
        result = strtok(NULL,delims); 
        numColumns = atoi(result); 
        for (i=0;i<numRows;i++){ //Malloc the columns 
        matrixA[i] = (int *) malloc(numColumns*sizeof(int)); 
        matrixB[i] = (int *) malloc(numColumns*sizeof(int)); 
        matrixC[i] = (int *) malloc(numColumns*sizeof(int)); 
        } 
        rowIdx = -1; 
        result = strtok(NULL,delims); 
       } 
       else if (!flagB){ //Processing Matrix A 
        matrixA[rowIdx][columnIdx] = atoi(result); 
        columnIdx++; 
        result = strtok(NULL,delims); 
       } 
       else if (flagB){ //Processing Matrix B 
        matrixB[rowIdx][columnIdx] = atoi(result); 
        columnIdx++; 
        result = strtok(NULL,delims); 
       } 
      } 
      rowIdx++; 
     } 
    } 
    else{ 
     printf("No Such File exists!\n"); 
    } 
    //At this point, matrix A and matrix B are both ready for computation. We will start to compute the product of the two matrices 
    int num_threads = numRows*numColumns; //The toal number of worker threads 
    pthread_t *worker_thread = (pthread_t *) malloc(sizeof(pthread_t)*num_threads); 
    ARGS_FOR_THREAD *args_for_thread; 


    for(i = 0; i < numRows; i++){ 
     for(j = 0; j < numColumns; j++){ 
      args_for_thread = (ARGS_FOR_THREAD *)malloc(sizeof(ARGS_FOR_THREAD)); // Allocate memory for the structure that will be used to pack the arguments 
      args_for_thread-> rowA = matrixA[i]; 
      //We need to allocate the corresponding column in B for multiplication 
      int k; 
      args_for_thread->columnB =(int *) malloc(sizeof(int)*numRows); 
      for (k=0;k<numRows;k++){ 
       args_for_thread-> columnB[k] = matrixB[k][j]; 
      } 
      //rowIdx and columnIdx gives the corresponding entry for matrix C 
      args_for_thread-> rowIdx = i; 
      args_for_thread-> columnIdx = j; 
      args_for_thread-> matrixC = matrixC;    
      if((pthread_create(&worker_thread[i], NULL, computeC, (void *)args_for_thread)) != 0){ 
       printf("Cannot create thread \n"); 
       exit(0); 
      } 
     } 
    } 
    // Wait for all the worker threads to finish 
    for(i = 0; i < num_threads; i++) 
     pthread_join(worker_thread[i], NULL); 
    //Print out the Final Matrix C 
    printMatrix(matrixC,numRows,numColumns); 
    //Clean up pointers 
    for(i = 0; i < numRows; i++){ 
     free(matrixA[i]); 
     free(matrixB[i]); 
     free(matrixC[i]); 
    } 
    free(matrixA); 
    free(matrixB); 
    free(matrixC); 
} 
void printMatrix(int** matrix,int numRows, int numColumns){ 
    int i,j; 
    for (i=0;i<numRows;i++){ 
     for (j=0;j<numColumns;j++){ 
      printf("%d ",matrix[i][j]); 
      if (j==numColumns-1){ 
       printf("\n"); 
      } 
     } 
    } 
} 
/* Function that will be executed by all the worker threads. It will compute the i,j entry for column C */ 
void *computeC(void *this_arg){ 
    ARGS_FOR_THREAD *arg = (ARGS_FOR_THREAD *) this_arg; 
    int rowIdx = arg->rowIdx; 
    int columnIdx = arg->columnIdx; 
    int *rowA = arg->rowA; 
    int *columnB = arg->columnB; 
    int **matrixC = arg->matrixC; 
    int i; 
    int sum = 0; 

    for (i=0;i<numRows;i++){ //Compute entry for matrix C. Since A,B are nxn square matrix, we can use either numRows or numColumns as the size 
     sum += rowA[i]*columnB[i]; 
    } 
    matrixC[rowIdx][columnIdx] = sum; 
    free((void *) arg); // Free up the structure 
    pthread_exit(NULL); 
} 

В чем проблема? Спасибо.

+2

В 'pthread_join (worker_thread [I], &1);' что вы делаете '& 1' для Является ли это опечатка –

+0

о, я прошу прощения, это код после модификации. Это должно быть просто NULL – zsljulius

ответ

2

Здесь:

pthread_create(&worker_thread[i] ... 

Вы создаете я * J темы, но вы только обеспечить worker_threads [я], следовательно, ваша программа продолжает использовать одни и те же переменные pthread_t. Позднее он завершится неудачей, когда вы попытаетесь присоединиться к потокам с неопределенными значениями pthread_t.

Заменить:?

pthread_create(&worker_thread[i*numColumns+j] ... 
+0

+1, хотя я предпочитаю (worker_thread + i * numColumns + j) для передачи адреса элемента массива (мне всегда казалось более понятным, если вы понимаете арифметику указателя). – WhozCraig

+0

миллион благодаря вам, гений! Я считаю, что я ошибаюсь. – zsljulius

Смежные вопросы