2016-04-06 30 views
0

Son zamanlarda iş için bir dizi sayısal analiz yapıyorum. Çoğunlukla nispeten basit kavramlar hakkında küçük miktarlarda veri için. Yaklaşan bir proje beklentisiyle, daha fazla hesaplama ile katlanarak daha karmaşık sistemlerde çalışmaya başladım. Çalışma süreleri onlarca saniyeden on dakikaya kadar çıktı. Pthreads kullanarak kod yazmayı öğrenmek için çalışma sürelerini hızlandırmaya karar verdim.Pthread Loop'ta Segmentasyon Hatası

Bu nedenle, matrisleri doldurmak için bir seri yöntem ve pitreler kullanan bir program üzerinde çalışıyorum. Bu programın her birini n yapmak için yazdım ve her koşunun ortalama zamanını aldım. Bu programı sadece bir pthread_t kullanarak çalıştırdığımda amaçlandığı gibi çalışır. Ek bir iş parçacığı eklediğimde, bir "Segmentation fault" hatası alıyorum.

Kodum şu:

fill.h

#ifndef FILL_H_ 
#define FILL_H_ 

#include <pthread.h>//Allows access to pthreads         
#include <sys/time.h>//Allows the ability to pull the system time     
#include <stdio.h>//Allows input and output          
#include <stdlib.h>//Allows for several fundamental calls       

#define NUM_THREADS 2                
#define MAT_DIM 50                
#define RUNS 1  

pthread_t threads[NUM_THREADS];            
pthread_mutex_t mutexmat; 

typedef struct{                 
    int id;                  
    int column;                  
    int* matrix[NUM_THREADS];                 
}WORKER; 
#endif 

fill.c

/*This routine will fill an array both in serial and parallel with random 
*numbers. It will also display the real time it took to accomplish each task*/ 

/* C includes */ 
#include "fill.h" 
/* Fills a matrix */ 
void fill(int start, int stop, int** matrix) 
{ 
    int i, j; 
    for(i = start; i < stop; i++) 
    { 
     for(j = 0; j < MAT_DIM; j++) 
      matrix[i][j] = rand() % 10; 
    } 
} 

void* work(void* threadarg) 
{ 
    /* Creates a pointer to a worker type variable*/ 
    WORKER *this_worker; 
    /* Points this_worker at what thread arg is pointing to*/ 
    this_worker = (WORKER*) threadarg; 
    /* Calculates my stopping point for this thread*/ 
    int stop = this_worker-> column + (MAT_DIM/NUM_THREADS); 
    /* Used to drive matrix */ 
    int i,j; 
    /* Fills portion of Matrix */ 
    for(i = this_worker-> column; i < stop; i++) 
    { 
     /* Prints the column that matrix is working on */ 
     printf("Worker %d working on column %d\n", this_worker->id, i); 

     for(j = 0; j < MAT_DIM; j++) 
     { 
      this_worker-> matrix[i][j] = rand() % 10; 
     } 
    } 
    /* Signals thread is done */ 
    printf("Thread %d done.\n", this_worker-> id); 
    /* Terminates thread */ 
    pthread_exit(NULL); 
} 

int main() 
{ 
/* Seeding rand */ 
    srand (time(NULL)); 
/* These will be used for loops */ 
    int i, j, r, t; 
/* Creating my matrices */ 
    int* matrix_serial[MAT_DIM]; 
    int* matrix_thread[MAT_DIM]; 
/* creating timeval variables */ 
    struct timeval t0, t1; 

/* Beginning serial solution */ 
    /* Creating timer for serial solution */ 
    gettimeofday(&t0, 0); 
    /* Creating serial matrix */ 
    for(i = 0; i < MAT_DIM; i++) 
     matrix_serial[i] = (int*)malloc(MAT_DIM * sizeof(int)); 

    /* Filling the matrix */  
    for(r = 0; r < RUNS; r++) 
     fill(0, MAT_DIM, matrix_serial); 
    /* Calculating how long it took to run */ 
    gettimeofday(&t1, 0); 
    unsigned long long int delta_t = (t1.tv_sec * 1000000 + t1.tv_usec) 
            - (t0.tv_sec * 1000000 + t0.tv_usec); 
    double t_dbl = (double)delta_t/1000000.0; 
    double dt_avg = t_dbl/(double)r; 
    printf("\nSerial Run Time for %d runs: %f\t Average:%f\n",r, t_dbl, dt_avg); 

/* Begin multithread solution */ 
    /* Creating the offset where each matrix will start */ 
    int offset = MAT_DIM/NUM_THREADS; 
    /* Creating a variable to store a return code */ 
    int rc; 
    /* Creates a WORKER type variable named mat_work_t */ 
    WORKER mat_work_t[NUM_THREADS]; 

    /* Allocating a chunk of memory for my matrix */ 
    for(i = 0; i < MAT_DIM; i++) 
     matrix_thread[i] = (int*)malloc(MAT_DIM * sizeof(int)); 

    /* Begin main loop */ 
    for(r = 0; r < RUNS; r++) 
    { 
    /* Begin multithread population of matrix */  
     for(t = 0; t < NUM_THREADS; t++) 
     { 
    /* Sets the values for mat_work_t[t] */ 
      mat_work_t[t].id = t; 
      mat_work_t[t].column = t * offset; 
      /* Points the mat_work_t[t].matrix at the matrix_thread */ 
      for(i = 0; i < MAT_DIM; i++) 
       mat_work_t[t].matrix[i] = &matrix_thread[i][0]; 

    /* Creates thread placing its return value into rc */ 
      rc = pthread_create(&threads[t], 
           NULL, 
           work, 
           (void*) &mat_work_t[t]); 
    /* Prints that a thread was successfully created */ 
      printf("Thread %d created.\n", mat_work_t[t].id); 
    /* Checks to see if a return code was sent. If it was it will print it. */ 
      if (rc) 
       { 
       printf("ERROR: return code from pthread_create() is %d\n", rc); 
       return(-1); 
       } 
     } 
    /* Makes sure all threads are done doing work before progressing */ 
     printf("Waiting for workers to finish.\n"); 
     for(i = 0; i < NUM_THREADS; i++) 
      pthread_join(threads[i], NULL); 

     printf("Work complete!\n"); 

    } 

    /* Prints out the last matrix that was created by the loop */ 
    for(i = 0; i < MAT_DIM; i++) 
     { 
      for(j = 0; j < MAT_DIM; j++) 
       printf("%d ",matrix_thread[i][j]); 
      printf("\n"); 
     } 
    /* Terminates thread */ 
    pthread_exit(NULL); 
} 

Ben gdb çalıştırdığınızda alıyorum: segmentasyon

[New Thread 0x7ffff7fd3700 (LWP 27907)] 
Thread 0 created. 
Worker 0 working on column 0 
Worker 0 working on column 1 
Worker 0 working on column 2 

Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x7ffff7fd3700 (LWP 27907)] 
0x0000000000400924 in work (threadarg=0x7fffffffd9c0) at fill.c:35 
35    this_worker-> matrix[i][j] = rand() % 10; 

Benim anlayış hatalar oldukça textbo Tamam: Erişmek için "sizinki" olmayan belleğe erişmeye çalıştığınızda bir segmentasyon hatası oluşur. Buradan, kodun bu matrisin depolandığı hafızada bir sorun yaşadığını biliyorum.

Sorularım:

  1. benim mantık doğru konunun doğasına mı?
  2. Neden bir iş parçacığı eklemek bu programın bozulmasına neden oluyor?
  3. Gelecekte bu tür bir sorunu gidermek için nasıl giderim (herhangi bir ipucu büyük ölçüde takdir edilecektir)?
  4. Son olarak, bunu nasıl düzeltirim (ipuçları veya bir çözüm büyük ölçüde takdir edilecektir)?

cevap

0

struct WORKER matrisinin boyutunun yalnızca NUM_THREADS olduğundan emin misiniz?

2 yerde bildirdiğiniz dizinin boyut sınırlamasının ötesine erişiyorsunuz.

bir ana işlevi NUM_THREADS burada
(bu sadece 2'dir) (50)

çalışma fonksiyonu

for(i = this_worker-> column; i < stop; i++) 
    { 
     /* Prints the column that matrix is working on */ 
     printf("Worker %d working on column %d\n", this_worker->id, i); 

     for(j = 0; j < MAT_DIM; j++) 
     { 
      this_worker-> matrix[i][j] = rand() % 10; 
     } 
    } 

yılında Burada

for(i = 0; i < MAT_DIM; i++) 
       mat_work_t[t].matrix[i] = &matrix_thread[i][0]; 

MAT_DIM kıyasla aslında çok düşük olduğunu matris [1] [j] 'ye erişene kadar döngü iyi gider, [2] [j] matrisine erişmeye çalıştığınızda segmentasyon hatası alırsınız, çünkü dizi boyutunu 2 olarak bildirmişsinizdir ve 3. bir (yani matris [2] [j]

+0

Bir milyona teşekkürler! Bugün anlamaya çalışırken kafamı klavyeye karşı çok dayak yedim. Beni sayısız saat hayal kırıklığına uğrattın, eminim. –

İlgili konular