Предоставляет ли pthreads какие-либо преимущества перед GCD? - PullRequest
19 голосов
/ 27 января 2010

Недавно изучив Grand Central Dispatch, я обнаружил, что многопоточный код довольно интуитивно понятен (с GCD). Мне нравится тот факт, что никаких блокировок не требуется (и тот факт, что он использует структуры данных без блокировок внутри), и что API очень прост.

Теперь я начинаю изучать нити, и я не могу не быть немного ошеломленным сложностью. Соединения потоков, взаимные исключения, условные переменные - все эти вещи не нужны в GCD, но имеют много вызовов API в pthreads.

Предоставляет ли pthread какие-либо преимущества перед GCD? Это более эффективно? Существуют ли случаи обычного использования, когда pthreads может делать то, чего не может GCD (исключая программное обеспечение уровня ядра)?

С точки зрения кроссплатформенной совместимости я не слишком обеспокоен. В конце концов, libdispatch с открытым исходным кодом, Apple представила свои изменения замыканий в виде патчей для GCC, clang поддерживает замыкания, и уже (например, FreeBSD) мы начинаем видеть некоторые реализации GCD сторонних разработчиков. В основном меня интересует использование API (конкретные примеры были бы великолепны!).

Ответы [ 6 ]

15 голосов
/ 30 декабря 2011

Я иду с другого направления: начал использовать pthreads в своем приложении, которое я недавно заменил на C ++ 11 std::thread. Теперь я играю с высокоуровневыми конструкциями, такими как псевдоусиливающий пул потоков и, еще более абстрактно, Intel Threading Building Blocks . Я бы посчитал, что GCD будет на уровне или даже выше чем TBB.

Несколько комментариев:

  • imho, pthread не сложнее , чем GCD: в своем основном ядре pthread на самом деле содержит очень мало команд (всего лишь несколько: использование только тех, которые упомянуты в OP, даст вам 95% + от функциональность, которая вам когда-либо понадобится). Как и любая библиотека более низкого уровня, именно то, как вы их собираете и как вы используете, дает вам ее силу. Не забывайте, что в конечном итоге библиотеки, такие как GCD и TBB, будут вызывать библиотеку потоков, такую ​​как pthreads или std::thread.
  • иногда, это не , что вы используете, а то, как вы его используете , который определяет успех против неудачи. Как сторонники библиотеки, TBB или GCD расскажут вам обо всех преимуществах использования их библиотек, но пока вы не попробуете их в реальном контексте приложения, все это имеет теоретическое преимущество . Например, когда я прочитал о том, как легко было использовать мелкозернистый параллель_ для , я сразу же использовал его в задаче, для которой, по моему мнению, может быть полезен параллелизм. Естественно, меня тоже привлек тот факт, что TBB будет обрабатывать все детали оптимального распределения нагрузки и распределения потоков. Результат? TBB занял в пять раз больше времени, чем однопоточная версия! Но я не виню TBB: в ретроспективе это, очевидно, случай неправильного использования parallel_for: когда я читал мелкий шрифт, я обнаружил накладные расходы, связанные с использованием parallel_for и предполагающие, что в моем случае затраты на переключение контекста и вызовы дополнительных функций перевешивают преимущества использования нескольких потоков. Таким образом, вы должны профилировать ваш случай, чтобы увидеть, какой из них будет работать быстрее. Возможно, вам придется реорганизовать свой алгоритм, чтобы использовать меньшие накладные расходы.
  • почему это происходит? Как pthread или никакие потоки не могут быть быстрее, чем GCD или TBB? Когда дизайнер разрабатывает GCD или TBB, он должен сделать предположения о среде, в которой будут выполняться задачи. На самом деле, библиотека должна быть достаточно общей, чтобы она могла обрабатывать странные, непредвиденные варианты использования разработчиком. Эти общие реализации не придут бесплатно. С другой стороны, библиотека будет запрашивать оборудование и текущую рабочую среду, чтобы лучше распределить нагрузку. Будет ли это работать на вашу пользу? Единственный способ узнать это - попробовать.
  • есть ли какая-либо польза от изучения библиотек более низкого уровня, таких как std::thread, когда библиотеки более высокого уровня доступны? Ответ - громкое ДА . Преимущество использования библиотек более высокого уровня заключается в абстрагировании от деталей реализации . недостаток в использовании библиотек более высокого уровня также является абстракцией от деталей реализации . При использовании pthreads я в высшей степени осведомлен об общем состоянии и времени жизни объектов, потому что, если я ослаблю свою охрану, особенно в средних и крупных проектах, я очень легко смогу получить условия гонки или ошибки памяти . Эти проблемы исчезают, когда я использую библиотеку более высокого уровня? На самом деле, нет. Кажется, что мне не нужно думать о них, но на самом деле, если я получу небрежные детали, реализация библиотеки также потерпит крах. Таким образом, вы обнаружите, что если вы понимаете конструкции нижнего уровня, все эти библиотеки действительно имеют смысл, потому что в какой-то момент вы будете думать о их реализации самостоятельно, если будете использовать вызовы более низкого уровня. Конечно, в этот момент обычно лучше использовать проверенный временем и отлаженный вызов библиотеки.

Итак, давайте разберем возможные реализации:

  • TBB / GCD библиотечные вызовы: наибольшее преимущество для начинающих потоков. Они имеют более низкие барьеры для входа по сравнению с изучением библиотек более низкого уровня. Однако они также игнорируют / скрывают некоторые ловушки использования многопоточности. Динамическая балансировка нагрузки сделает ваше приложение более переносимым без дополнительного кодирования с вашей стороны.
  • pthread и std::thread вызовы: на самом деле очень мало вызовов для изучения, но для их правильного использования требуется внимание к деталям и глубокое понимание работы вашего приложения. Если вы сможете понимать потоки на этом уровне, API библиотек более высокого уровня, безусловно, будет иметь больше смысла.
  • однопоточный алгоритм : давайте не будем забывать о преимуществах простого однопоточного сегмента. Для большинства приложений однопоточность проще для понимания и намного менее подвержена ошибкам, чем многопоточность. На самом деле, во многих случаях это может быть подходящим выбором дизайна. В том-то и дело, что реальное приложение проходит через различные многопоточности и однопоточности: может быть, многопоточность не нужна постоянно.

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

Да, и ОП спросил о случаях, когда thread_pool не подходит. Простой случай: если у вас плотный цикл, для которого не требуется много циклов на цикл, использование thread_pool может стоить дороже, чем преимущества без серьезной переработки. Также следует помнить о накладных расходах вызовов функций, таких как лямбда, через пулы потоков по сравнению с использованием одного узкого цикла.

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

14 голосов
/ 27 января 2010

Это непреодолимое чувство, которое вы испытываете ... именно поэтому был изобретен GCD.

На самом базовом уровне есть потоки, pthreads - это POSIX API для потоков, поэтому вы можете писать код в любой совместимой ОС и ожидать, что он будет работать. GCD построен поверх потоков (хотя я не уверен, что они действительно использовали pthreads в качестве API). Я считаю, что GCD работает только на OS X и iOS - в двух словах это его главный недостаток.

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

4 голосов
/ 27 января 2010

GCD - это технология Apple, и она не является кроссплатформенной; Pthread доступны практически на всем: от OSX, Linux, Unix, Windows ... включая этот тостер

GCD оптимизирован для параллелизма пула потоков. Pthreads - это (как вы сказали) очень сложные строительные блоки для параллелизма, вам остается разрабатывать свои собственные модели. Я настоятельно рекомендую взять книгу на эту тему, если вам интересно узнать больше о pthreads и различных моделях параллелизма.

3 голосов
/ 27 января 2010

Как и любой декларативный / вспомогательный подход, такой как openmp или Intel TBB GCD, должен быть очень хорош в смущающе параллельных проблемах и, вероятно, легко справится с наивным параллельная сортировка. Я бы посоветовал вам все же выучить логи. Вы лучше поймете параллелизм, сможете применять правильный инструмент в каждой конкретной ситуации, и если ни для чего иного - есть тонна кода на основе pthread - вы сможете читать «устаревший» код.

0 голосов
/ 15 июля 2013

GCD абстрагирует потоки и выдает очереди на отправку. Он создает потоки, которые он считает необходимыми, с учетом количества доступных процессорных ядер. GCD является открытым исходным кодом и доступен через библиотеку libdispatch. FreeBSD включает libdispatch начиная с 8.1. Блоки GCD и C - это вклад мэра Apple в сообщество программистов на C. Я бы никогда не использовал ни одну ОС, не поддерживающую GCD.

0 голосов
/ 23 сентября 2010

Обычно: 1 задача на реализацию Pthread использует мьютексы (функция ОС).
НОД: 1 задание на блок, сгруппированное в очереди. 1 поток на виртуальный процессор может получить очередь и работать без мьютексов через все задачи. Это уменьшает накладные расходы на управление потоками и мьютекс, что должно повысить производительность.

...