2015-04-30 6 views
0

Я могу выслать свой код, если необходимо, но мой вопрос в основном концептуальный. Я реализую гауссово исключение с потоком. У меня есть p preads, работающие на матрице nxn в главном порядке столбца. Прежде чем какой-либо p-поток может начать работать в столбце, необходимо выполнить операции над строкой, чтобы переместить строку с наибольшим значением в этом столбце до диагонали. Поэтому мне нужен каждый поток, чтобы ждать, а затем работать в унисон. В настоящее время в каждом столбце каждый поток проверяет свой идентификатор, один с id = 0 будет выполнять операции над строкой. Моя проблема заключается в том, как получить все потоки, но id = 0, чтобы ждать, а затем работать в Unison.Pthread условные обозначения

Я пробовал использовать блокировки и условные обозначения мьютекса. Они не работают, потому что они дают все права доступа к одному потоку. Из того, что я понимаю, можно только блокировать поток таким образом, запросив блокировку, где она уже существует, поэтому она должна ждать. Это было бы проблемой в моем случае, потому что я не хочу, чтобы ни один из не-нитей имел блокировку, после того как они разблокированы, я хочу, чтобы они свободно работали, пока они не закончат работу над столбцом.

Я пытался избежать блокировок Mutex, просто имея глобальную переменную colReady, равную 0. Ненулевые нити while, пока colReady = True. Логически это имеет смысл, но он не работал программно.

#include <stdio.h> 
#include <math.h> 
#include <stdlib.h> 
#include <pthread.h> 

#define n 20 
#define numThr 3 

double **matrix; 
int pivotReady[n] = { 0 }; 

pthread_cond_t cond_pivot_ready; 
pthread_mutex_t cond_mutex; 

int swapRows (int row1, int row2) 
{ 
    double *tempRow = matrix[row1]; 
    matrix[row1] = matrix[row2]; 
    matrix[row2] = tempRow; 
    return 0; 
} 

void randinit() 
{ 
    int i, j; 
    for (i = 0; i < n; i++) { 
     for (j = 0; j < n + 1; j++) { 
      matrix[i][j] = drand48(); 
     } 
    } 
} 

void rowReduce (void *arg); 

void printMatrix() 
{ 
    int i, j; 
    for (i = 0; i < n; i++) { 
     for (j = 0; j < n + 1; j++) { 
      printf (" %4.2f ", matrix[i][j]); 
     } 
     printf ("\n"); 
    } 
} 

int main() 
{ 
    pthread_cond_init (&cond_pivot_ready, NULL); 
    pthread_mutex_init (&cond_mutex, NULL); 

    int i, j; 
    double temp; 
    pthread_t p_threads[numThr]; 
    pthread_attr_t attr; 
    pthread_attr_init (&attr); 

    //create matrix 
    matrix = malloc (sizeof (double *) * n); 
    for (i = 0; i < n; i++) { 
     *(matrix + i) = malloc (sizeof (double) * (n + 1)); 
    } 

    randinit(); 

    for (i = 0; i < numThr; i++) { 
     pthread_create (&p_threads[i], &attr, rowReduce, (void *) ((long) i)); 
    } 

    for (i = 0; i < numThr; i++) { 
     pthread_join (p_threads[i], NULL); 
    } 
    printf ("Final Matrix:\n"); 
    printMatrix(); 

    return 0; 
} 

void rowReduce (void *arg) 
{ 
    int id = (int) arg; 
    int i, pivot, row; 
    double ratio, temp, max; 
    int maxRow; 

    for (pivot = 0; pivot < n - 1; pivot++) { 

     //PIVOT THREAD 
     if (id == 0) { 
      pthread_mutex_lock (&cond_mutex); 
      max = matrix[pivot][pivot] 
       maxRow = pivot; 
      for (i = pivot + 1; i < n; i++) { 
       temp = matrix[i][pivot]; 
       if (temp > max) { 
        max = temp; 
        maxRow = i; 
       } 
      } 
      swapRows (pivot, maxRow); 

      pivotReady[pivot] = 1; 
      pthread_cond_signal (&cond_pivot_ready); 

      for (row = pivot + 1 + id; row < n; row += numThr) { 

       ratio = matrix[row][pivot]/matrix[pivot][pivot]; 
       printf ("t1: row = %d, piv = %d, ratio = %f\n", row, pivot, 
         ratio); 
       for (int i = pivot; i < n + 1; i++) { 
        matrix[row][i] -= ratio * matrix[pivot][i]; 
       } 
      } 
      pthread_mutex_unlock (&cond_mutex); 
     } 
     //NON-PIVOT THREAD 
     else { 
      pthread_mutex_lock (&cond_mutex); 
      while (!(pivotReady[pivot])) { 
       pthread_cond_wait (&cond_pivot_ready, &cond_mutex); 
      } 

      for (row = pivot + 1 + id; row < n; row += numThr) { 
       ratio = matrix[row][pivot]/matrix[pivot][pivot]; 
       for (int i = pivot; i < n + 1; i++) { 
        matrix[row][i] -= ratio * matrix[pivot][i]; 
       } 
      } 
      pthread_mutex_unlock (&cond_mutex); 

     } 

    } 

    //printf("rowReduce called with id = %d\n", id); 
    pthread_exit (0); 
} 

Эта программа ДОЛЖНА напечатать случайную матрицу, которая была помещена в верхнюю треугольную форму.

+0

Вы должны смотреть на 'pthread_barrier_wait()'. – JS1

+1

Примечание: если матрица HUUUGE (действительно огромная!), Попытка создания параллельной версии алгоритма не окупается. В более абстрактном виде: приложение, которое будет использовать это, вероятно, должно будет решить эту проблему много раз, и вам лучше запустить параллельные версии однопоточного алгоритма. Чтобы он полностью окупился, вам нужно было бы найти безошибочный подход к алгоритму. С другой стороны, использование параллелизма данных было бы хорошей идеей. Ключевое слово: SIMD. – BitTickler

+0

Я не смотрел ваш код, но на основе вашего описания почему бы не основной поток сортировать строки, а затем запустить другие потоки после подготовки матрицы? –

ответ

0

Вам нужно всего лишь удерживать cond_mutex, пока вы обращаетесь к pivotReady[pivot], потому что это единственное общее состояние, которое оно защищает.

Вы также должны использовать pthread_cond_broadcast() вместо pthread_cond_signal(), потому что вам нужно всех ожидающих потоков, чтобы продолжить, как только стержень будет готов.

После небольшого рефакторинга, так что код обработки строки не повторяется, это выглядит следующим образом:

for (pivot = 0; pivot < n - 1; pivot++) { 

    //PIVOT THREAD 
    if (id == 0) { 
     max = matrix[pivot][pivot]; 
     maxRow = pivot; 
     for (i = pivot + 1; i < n; i++) { 
      temp = matrix[i][pivot]; 
      if (temp > max) { 
       max = temp; 
       maxRow = i; 
      } 
     } 
     swapRows (pivot, maxRow); 

     pthread_mutex_lock (&cond_mutex); 
     pivotReady[pivot] = 1; 
     pthread_cond_broadcast (&cond_pivot_ready); 
     pthread_mutex_unlock (&cond_mutex); 
    } 
    //NON-PIVOT THREAD 
    else { 
     pthread_mutex_lock (&cond_mutex); 
     while (!(pivotReady[pivot])) { 
      pthread_cond_wait (&cond_pivot_ready, &cond_mutex); 
     } 
     pthread_mutex_unlock (&cond_mutex); 
    } 

    for (row = pivot + 1 + id; row < n; row += numThr) { 
     ratio = matrix[row][pivot]/matrix[pivot][pivot]; 
     for (int i = pivot; i < n + 1; i++) { 
      matrix[row][i] -= ratio * matrix[pivot][i]; 
     } 
    } 
} 
Смежные вопросы