Реализация блокировки между pthreads без условных переменных - PullRequest
0 голосов
/ 25 октября 2011

Я реализую шаблон проектирования босс / работник, используя pthreads в Linux. Я хочу иметь ветку босса, которая постоянно проверяет работу, и если есть работа, то будит спящего работника, чтобы сделать работу. Мой вопрос: какой тип синхронизации / механизма IPC я должен использовать для достижения наименьшей задержки между передачей моего босса потоком моему работнику и моим работником, просыпающимся?

Простое решение - использовать условные переменные Pthread и вызвать pthread_cond_signal в потоке босса и pthread_cond_wait в каждом из рабочих потоков, но мне интересно Есть ли что-то быстрее, что я могу использовать для реализации блокировки и сигнализации? Например, как использовать каналы между боссом и рабочими потоками?

как я могу измерить производительность одного типа IPC по сравнению с другим? Например, я вижу тесты для pipe () и fork (), но ничего для использования pipe () в качестве связи между потоками.

Дайте мне знать, если я смогу уточнить что-нибудь в моих вопросах!

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

Ответы [ 3 ]

2 голосов
/ 25 октября 2011

Реализация pthreads в glibc использует низкоуровневые блокировки futex для реализации pthread_cond_wait() / pthread_cond_signal(). Futexes были разработаны, чтобы быть быстрым синхронизирующим примитивом, поэтому они, вероятно, превзойдут каналы или подобные методы (по крайней мере, использование каналов требует копирования байта в пространство ядра и из него, которое не требуется для фьютексов).

Если pthread_cond_wait() / pthread_cond_signal() хорошо отображает вашу проблему (и, похоже, они это делают), то единственный способ превзойти их - это реализовать что-то на фьютексах самостоятельно (например, вы можете устранить обработка отмены потока, если вы этим не пользуетесь).

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

1 голос
/ 25 октября 2011

Что вы должны сделать в первую очередь, так это убедиться, что вам нужно что-то быстрее. Поскольку передача сигналов pthread реализована с использованием futex, где futex обозначает быстрый мьютекс пространства пользователя, я не думаю, что вы сможете выполнить их.

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

Но что вы должны сделать, так это подумать о своей проблеме:

  • если у вас постоянно есть работа, то ваш рабочий поток всегда занят. Работа будет завершена, когда предыдущая работа будет завершена, и вы не заботитесь о задержке.

  • Если имеет значение задержка между боссом, обнаружившим событие, и рабочим, начинающим работать, то почему вы используете шаблон босс -> работник?

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

Реализуйте свой дизайн с помощью pthread_signal или, возможно, semp_post () / sem_wait (), а затем посмотрите, где на самом деле ваша задержка и действительно ли это проблема.

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

Я бы догадался, что сигнал и ожидание будет лучшим. Большинство ОС распознают потоки и могут оставлять их бездействующими, пока не наступит прерывание. С трубами рабочий должен будет просыпаться и проверять трубу на выход. Лучшее тестирование на эффективность, которое я нашел, обычно заключалось в использовании команды unix для определения времени выполнения от начала до конца (при условии, что программа не должна работать в фоновом режиме), для этого нужно настроить скрипт. раз и сравните.

...