Matrix Multiplication using multi-threads gets segmentation fault

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Tosh2pointO
    New Member
    • Sep 2010
    • 3

    Matrix Multiplication using multi-threads gets segmentation fault

    Hello, I'm trying to write a program that calculates up to a 1024 x 1024 matrix using multi-threading. For example, I need to run a 1024 x 1024 using 256, 64, 16 or 4 threads. Or I need to run a 64 x 64 matrix using 16 or 4 threads. All the Matrices are square. I thought I coded my program correctly, however I get a segmentation fault when I use a 720 x 720 matrix or higher, heres the code.
    Code:
    #include <iostream>
    #include <stdio.h>
    #include <pthread.h>
    
    using namespace std;
    
    
    const int   DIM = 720; //works up to 719, crashes at 720
    const int   num_of_thr = 4;
    int         matrix_A[DIM][DIM];
    int         matrix_B[DIM][DIM];
    int         c[DIM][DIM];
    
    struct v
    {
        int i;
        int j;
    };
    
    //worker thread
    void* matrix_multi(void* data)
    {    
        for(int i = 0; i < DIM; i++)
        {
            for(int j = 0; j < DIM; j++)
            {
                c[i][j] = 0;
                for(int k = 0; k < DIM; k++)
                {
                    c[i][j] += matrix_A[i][k] * matrix_B[k][j];
                }
            }
        }
        pthread_exit(0);
    }
    
    int main()
    {
    
        pthread_t thr_id[DIM][DIM];
        pthread_attr_t thr_attr;
        pthread_attr_init(&thr_attr);
    
    
    
       //Filling the Matrices
        for(int i = 0; i < DIM; i++)
        {
            for(int j = 0; j < DIM; j++)
            {
                matrix_A[i][j]= i + j;
                matrix_B[i][j] = i + 3;
            }
        }
    
    
        //create the threads
        for(int i = 0; i < num_of_thr/2; i++)
        {
            for(int j = 0; j < num_of_thr/2; j++)
            {
                struct v *data = (struct v *) malloc(sizeof(struct v));
                data->i = i;
                data->j = j;
                pthread_create(&thr_id[i][j],NULL,matrix_multi,  &data);
            }
        }
    
        //joining the threads
        for(int i = 0; i < num_of_thr/2; i++)
        {
            for(int j = 0; j < num_of_thr/2; j++)
            {
            pthread_join(thr_id[i][j],NULL);
            }
        }
    
         return 0;
    }
    Any help would be appreciated, thanks in advance.
  • ashitpro
    Recognized Expert Contributor
    • Aug 2007
    • 542

    #2
    I just ran this code on my CentOS machine (g++ 4.1.2).
    It worked pretty well, no seg fault. Even if I increase the number of threads and dimensions.

    Comment

    • newb16
      Contributor
      • Jul 2008
      • 687

      #3
      Seems that your compiler doesn't like huge variables in data segment (matrix_a) and/or stack (thr_id). Allocate them on the heap. (btw - why do you need thr_id be of size [DIM][DIM] when you only fill it to num_of_thr/2 in each dimension?

      Comment

      • Tosh2pointO
        New Member
        • Sep 2010
        • 3

        #4
        Thanks for the quick help. I changed my code quite a bit since yesterday. However I now get a "invalid conversion from `void*' to `__pthread_t**" on line 63 of my code. Here is the updated code:
        Code:
        #include <pthread.h>
        #include <stdlib.h>
        #include <stdio.h>
        
        #define SIZE 10			/* Size of matrices */
        int N;				/* number of threads */
        
        int A[SIZE][SIZE], B[SIZE][SIZE], C[SIZE][SIZE];
        
        void fill_matrix(int m[SIZE][SIZE])
        {
          int i, j, n = 0;
          for (i=0; i<SIZE; i++)
            for (j=0; j<SIZE; j++)
              m[i][j] = n++;
        }
        
        void print_matrix(int m[SIZE][SIZE])
        {
          int i, j = 0;
          for (i=0; i<SIZE; i++) {
            printf("\n\t| ");
            for (j=0; j<SIZE; j++)
              printf("%2d ", m[i][j]);
            printf("|");
          }
        }
        
        
        void* mmult (void* slice)
        {
          int s = (int)slice;
          int from = (s * SIZE)/N;	/* note that this 'slicing' works fine */
          int to = ((s+1) * SIZE)/N;	/* even if SIZE is not divisible by N */
          int i,j,k;
        
          printf("computing slice %d (from row %d to %d)\n", s, from, to-1);
          for (i=from; i<to; i++)
            for (j=0; j<SIZE; j++) {
              C[i][j]=0;
              for (k=0; k<SIZE; k++)
        	C[i][j] += A[i][k]*B[k][j];
            }
        
          printf("finished slice %d\n", s);
          return 0;
        }
        
        int main(int argc, char *argv[])
        {
          pthread_t *thread;
          int i;
        
          if (argc!=2) {
            printf("Usage: %s number_of_threads\n",argv[0]);
            exit(-1);
          }
        
          N=atoi(argv[1]);
          fill_matrix(A);
          fill_matrix(B);
          thread = malloc(N*sizeof(pthread_t));
        
          for (i=1; i<N; i++) {
            if (pthread_create (&thread[i], NULL, mmult, (void*)i) != 0 ) {
              perror("Can't create thread");
              exit(-1);
            }
          }
        
          /* master thread is thread 0 so: */
          mmult(0);
        
          for (i=1; i<N; i++) pthread_join (thread[i], NULL);
        
          printf("\n\n");
          print_matrix(A);
          printf("\n\n\t       * \n");
          print_matrix(B);
          printf("\n\n\t       = \n");
          print_matrix(C);
          printf("\n\n");
        
          return 0;
        
        }
        Any help would be appreciated, thanks in advance

        Comment

        • ashitpro
          Recognized Expert Contributor
          • Aug 2007
          • 542

          #5
          Explicit type casting should work..

          Code:
          thread = (pthread_t *)malloc(N*sizeof(pthread_t));

          Comment

          Working...