2016-05-06 7 views
-1

У меня возникает ошибка сегментации при запуске моего кода на 8 процессорах, но он отлично работает для 1 и 4 процессоров.Ошибка сегментации (сбрасывается ядром) при изменении количества процессоров в lpthreads

Я использую библиотеку lpthread, и это функция, которую я выполняю в каждом потоке. Если вам нужен еще один код, я могу добавить еще.

void *compute_gauss(void *threadid){ 

    int local_row, local_norm, col; 
    float multiplier; 
    long tid; 
    tid = (long)threadid; 

    fprintf(stdout, "Thread %ld has started\n", tid); 

    while (global_norm < N){ 

    while (global_row < N) { 
     pthread_mutex_lock(&global_row_lock); 
     local_row = global_row; 
     global_row++; 
     pthread_mutex_unlock(&global_row_lock); 

     print_inputs(); 
     multiplier = A[local_row][global_norm]/A[global_norm][global_norm]; 

     for (col = global_norm; col < N; col++) { 
     A[local_row][col] -= A[global_norm][col] * multiplier; 
     } 

     B[local_row] -= B[global_norm] * multiplier; 

    } 

    pthread_barrier_wait(&barrier); 
    if (tid == 0){ 
     global_norm++; 
     global_row=global_norm+1; 
    } 
    pthread_barrier_wait(&barrier); // wait until all threads arrive 
    } 
} 

Вот функция вызова, где я инициализировать барьеры:

void gauss() { 
    int norm, row, col; /* Normalization row, and zeroing 
          * element row and col */ 
    int i = 0; 
    float multiplier; 
    pthread_t threads[procs]; //declared array of threads equal in size to # processors 
    global_norm = 0; 
    global_row = global_norm+1; 

    printf("Computing Parallelized Algorithm.\n"); 

    pthread_barrier_init(&barrier, NULL, procs); 

    /* Gaussian elimination */ 
    for (i = 0; i < procs; i++){ 
     pthread_create(&threads[i], NULL, &compute_gauss, (void *)i); 
    } 

    printf("finished creating threads\n"); 

    for (i = 0; i < procs; i++){ 
     pthread_join(threads[i], NULL); 
    } 

    printf("finished joining threads\n"); 
    /* (Diagonal elements are not normalized to 1. This is treated in back 
    * * substitution.) 
    *  */ 

    fprintf(stdout, "pre back substition"); 
    /* Back substitution */ 
    for (row = N - 1; row >= 0; row--) { 
     X[row] = B[row]; 
     for (col = N-1; col > row; col--) { 
     X[row] -= A[row][col] * X[col]; 
     } 
     X[row] /= A[row][row]; 
    } 
    fprintf(stdout, "post back substitution"); 
    } 
+1

Хорошо. Это хорошо знать. – immibis

+0

Что такое backtrace segfault? – fluter

+0

Stack следы пожалуйста? –

ответ

1

Вот один пример того, как код согрешения массива, пожалуйста, указать, если я не права:

// suppose global_row = N - 1; 
while (global_row < N) { 
    pthread_mutex_lock(&global_row_lock); // thread 2 waits here, global_row is N - 1; 
    local_row = global_row;     // thread 1 is here, global_row is N - 1; 
    global_row++; 
    pthread_mutex_unlock(&global_row_lock); 

    // when thread 2 goes here, local_row is going to be N, out of array boundary. 
    multiplier = A[local_row][global_norm]/A[global_norm][global_norm]; 
+0

Да, это имеет большой смысл! Я забыл, что поток может попасть в замок таким образом. Спасибо Гарольду! – MichaelGofron

0

Вы не включили достаточно кода, так что я могу проверить вас программу. Тем не менее, я уверен, что проблема в том, что у вас нет защиты mutext global_norm, global_row и print_inputs(). Вам необходимо защитить их с помощью мьютекса, или вам нужно использовать оператор атомного инкремента. Вы не видите аварии под отладчиком, потому что это изменяет время.

+0

global_norm не должно быть проблемой, потому что я препятствую этому и обновляю его между барьером только на одну нить. Что касается global_row, он заблокирован, как видно из кода, а print_inputs() печатает только буквы A и B, которые они не записывают. – MichaelGofron

0

Если вы не проверяете возвращаемое значение pthread_barrier_wait и проверяете на PTHREAD_BARRIER_SERIAL_THREAD?

Непонятно также, почему вы дважды вызываете pthread_barrier_wait.

+0

Я не верю, что это работает pthread_barrier_wait. Согласно документации, он просто ждет, пока все нити достигнут этой точки, а затем вернутся к состоянию последнего init. Сначала я называю это, чтобы предотвратить обновление global_norm для других значений, и я вызываю его впоследствии, чтобы предотвратить запуск других потоков со старым значением global_norm и global_row. – MichaelGofron

+0

Если вы используете возвращаемое значение pthread_barrier_wait, вам не нужно жестко указывать этот поток с идентификатором нуля, обновляющим глобальный. У вас должно быть что-то вроде: rv = pthread_barrier_wait (...); if (rv == PTHREAD_BARRIER_SERIAL_THREAD) {// обновлять глобальные переменные} Если вы читаете документы, pthread_barrier_wait возвращает такое значение, чтобы получить только один поток PTHREAD_BARRIER_SERIAL_THREAD. Я не уверен, что вы гарантированы, что pthread_create создаст поток с tid == 0 – bpeikes

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