как справиться с барьерами с выходом нитей - PullRequest
2 голосов
/ 25 ноября 2011

Псевдокод:

void * thread_start(void *arg) {
    while (1) {
        /* for each column. Only run columns the thread_num
           is assigned to */
        column_count = thread_num;
        for (; column_count < dim - 1; column_count+=threads) {
             /* do thread work for data chunk */
        }

        /* barrier */
        barrier_result = pthread_barrier_wait(barrier);

        if (not_finished == 0) {
            /* finished */
            break;
            /* break while loop, end thread.
               The barrier is now broken because it is no longer
               getting called by this thread */
        }

        /* we are not finished, loop around and 
           do thread work on next data chunk */
    }
}

Моя проблема с барьерами заключается в том, как вы справляетесь с потоками, заканчивающимися раньше других потоков?

Барьер означает, что каждый поток долженподождать всех остальных потоков.

Какие существуют методы для обеспечения завершения всех потоков в одно и то же время?

Я пытался продолжить цикл, но игнорировал «работу потока», но в этом случае все8 потоков заканчиваются, и нет никакого разумного способа сообщить темам «все готово, вы можете выйти сейчас»

Редактировать:

Алгоритм:

  1. Выполнение операций над сегментом фрагмента данных
  2. , если сегмент фрагмента данных потока завершен.
  3. Ожидание барьера.
  4. Один поток заменяет фрагментданных с некоторыми новыми данными
  5. повторить 1.

Изменить 2:

Есть ли какой-нибудь элегантный способ перезаписать барьер с помощьюбарьер, который на один размер меньше?(без установки мьютекса вокруг барьера)

1 Ответ

0 голосов
/ 25 ноября 2011

Вы гарантируете, что потоки заканчиваются в одно и то же время самой природой логики программы.Если ваш алгоритм требует, чтобы потоки выходили в разное время, то барьеры не являются подходящим механизмом управления параллелизмом для этого конкретного алгоритма.

РЕДАКТИРОВАТЬ:

Вы можете атомарно увеличивать"Законченный_чет" и цикл, не выполняющий никакой работы, кроме участвующего в барьере, в то время как это число меньше, чем счетчик барьеров (защита чтения / записи в законченный_чет с соответствующими мьютексами).

РЕДАКТИРОВАТЬ: Я не уверен, хорошо ли я понимаю ваше добавленное описание, я просто написал это на основе вашего исходного кода, возможно, оно будет работать для вас:

int finished_count;

void * thread_start(void *arg) {
    int finished = 0;

    while (1) {

        if (finished) {
            pthread_mutex_lock (&finished_lock);
            if (finished_count == 8) {
                pthread_mutex_unlock (&finished_lock);
                break;
            }
            pthread_mutex_unlock (&finished_lock);
        } else {
            /* for each column. Only run columns the thread_num
               is assigned to */
            column_count = thread_num;
            for (; column_count < dim - 1; column_count+=threads) {
                /* do thread work for data chunk */
            }

            /* set "finished" as appropriate */

            /* Check if we have just finished.  */
            if (finished) {
                pthread_mutex_lock (&finished_lock);
                ++finished_count;
                pthread_mutex_unlock (&finished_lock);
            }
        }

        barrier_result = pthread_barrier_wait(barrier);
    }

    return 0;
}

РЕДАКТИРОВАТЬ:

Чтобы пояснить мой комментарий выше о копировании или повторной инициализации, POSIX говорит:

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_barrier_init.html

Результаты не определены, если pthread_barrier_init () вызывается с указаниемуже инициализированный барьер.

и

Только объект, на который ссылается барьер, может использоваться для выполнения синхронизации.Результат обращения к копиям этого объекта в вызовах pthread_barrier_destroy () или pthread_barrier_wait () не определен.

...