Возможные способы реализации динамического барьера в многопоточных программах - PullRequest
1 голос
/ 01 августа 2011

Я прочитал это в газете ...

Следовательно, наш инструмент только проверяет поток, когда он выполняется в известной безопасной точке: вход в ядро, выход из ядра или определенный прерываемые сны в ядре, которое мы определили как безопасное. Поток, который инициирует многопоточную ветвь, создает барьер на которого он ждет, пока все остальные потоки не достигнут безопасной точки. Раз все нити достигают барьера, исходная нить создает контрольную точку, затем позволяет другим потокам продолжить выполнение.

Теперь мой вопрос: может ли кто-нибудь догадаться, о каком барьере говорят авторы? Как поток создает барьер и динамически вставляет барьер в другие потоки? Любой рабочий пример будет высоко оценен.

EDITED

Пожалуйста, не говорите, используйте pthread_barrier_wait , потому что это не вопрос. Здесь, очевидно, авторы имеют поток, который динамически вставляет барьеры в другие потоки. Я хочу знать, как?

Ответы [ 5 ]

4 голосов
/ 02 августа 2011

Бумага, о которой вы спрашиваете, выглядит как "Respec: эффективное онлайн-многопроцессорное воспроизведение с помощью спекуляций и внешнего детерминизма" .В документе упоминается:

Мы изменили ядро ​​Linux для реализации наших методов.

и

Поэтому мы создали новый примитив Linux, называемый многопоточным форком, который создает дочерний процесс с тем же числом потоков, что и его родительский.

Поэтому, когда в статье говорится, что

Respec проверяет только поток, когда он выполняется в известной безопасной точке: вход в ядро, выход из ядра или некоторые прерывистые сны в ядре, которыемы решили быть в безопасности.Поток, который инициирует многопоточную ветвь, создает барьер, на котором он ожидает, пока все другие потоки не достигнут безопасной точки.Как только все потоки достигают барьера, исходный поток создает контрольную точку, а затем позволяет другим потокам продолжать выполнение.

Я бы предположил, что среди модификаций, которые они внесли в ядро ​​Linux, была логика, что потоки врегистрируемый процесс «войдет» в барьер, когда он достигнет одной из этих «безопасных точек» (я также предположил бы, только если был создан «многопоточный форк», созданный для создания барьера).Поскольку это происходит в ядре, было бы достаточно легко реализовать барьер - на самом деле ничего динамического не происходит.Модифицированное ядро ​​имеет барьеры, реализованные в этих стратегически безопасных точках.

На самом деле я не читал статью (просто просмотрел несколько бит).Мне не совсем понятно, что может произойти, если один или несколько потоков выполняют работу, не требующую входа в ядро ​​в течение длительного периода времени - похоже, что система зависит от потоков, которые достигают этих явных безопасных точек.Поэтому потоки не должны слишком долго задерживаться в цикле, интенсивно использующем ЦП (что, вероятно, не является проблемой для подавляющего большинства программ):

Обратите внимание, что фактическое время выполнения эпохи может быть большечем интервал эпохи из-за нашей реализации барьера;контрольная точка не может быть взята, пока все нити не достигнут барьера.

2 голосов
/ 01 августа 2011

Хорошо, учитывая, что ваш вопрос помечен как linux и pthreads, я могу только представить, что он относится к барьерам pthread:

Вот пример:

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

pthread_barrier_t bar;
pthread_t  th;

void* function(void*)
{  
    printf("Second thread before the barrier\n");
    pthread_barrier_wait(&bar);
    printf("Second thread after the barrier\n");
    return NULL;
}

int main()
{
    printf("Main thread is beginning\n");
    pthread_barrier_init(&bar, NULL, 2);
    pthread_create(&th, NULL, function, NULL); 
    pthread_barrier_wait(&bar);
    printf("Main thread has passed the barrier\n");
    pthread_join(&th,NULL);
    pthread_barrier_destroy(&bar);
    return 0;
}
0 голосов
/ 02 августа 2011

Барьер потока ОС - это не более чем состояние в памяти.Если вы можете разделить это состояние между потоками (путем правильной инициализации потоков), то потоки могут использовать этот барьер.

По существу основной поток выполняет:

CreateAllThreads(&barrier);
StartAllThreads();
EnterBarrier(&barrier);

Все остальные потоки выполняют:

RuntimeInitialize();
EnterBarrier(&barrier);

Выше приведен только очень грубый псевдокод только для иллюстративных целей.

0 голосов
/ 01 августа 2011

Простой: используйте API-вызов pthread_barrier_wait pthread.

Для получения подробной информации см. Справочную страницу: http://linux.die.net/man/3/pthread_barrier_wait

0 голосов
/ 01 августа 2011

Барьер - это довольно стандартный примитив синхронизации .

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

Я знаю, что вы спрашиваете о C / C ++, но взгляните на Java CyclicBarrier, поскольку концепция там достаточно хорошо объяснена.

Поскольку выВы спрашиваете о pthreads, взгляните на pthread_barrier_init и др.

edit

Но в этом случае,поток, казалось бы, динамически вставляет барьеры в другие потоки.Как?

Трудно ответить на этот вопрос без какого-либо контекста (например, бумаги, которую вы читаете).

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

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

Надеюсь, я не слишком далеко в своем предположении о контексте.

...