Предоставляет ли pthreads какие-либо преимущества перед GCD?

19

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

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

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

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

    
задан Mike 27.01.2010 в 05:47
источник
  • Это кажется уместным: stackoverflow.com/questions/14177689/... –  user1031420 29.05.2013 в 23:25

6 ответов

12

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

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

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

    
ответ дан slebetman 27.01.2010 в 05:57
источник
  • Таким образом, помимо кросс-платформенной совместимости, нет недостатков в использовании GCD (даже скорость)? –  Mike 27.01.2010 в 06:01
  • На самом деле скорость является одним из преимуществ GCD перед наивным использованием pthreads. Даже сложные самореализованные потоковые пулы в pthreads, таких как Apache, не так хороши, как GCD, потому что GCD лучше знает ОС и базовое оборудование. –  slebetman 27.01.2010 в 06:06
  • Библиотеки Pthreads работают так же быстро, как это делают разработчики. Они должны быть написаны специально для архитектуры ОС и ЦП (операции Atomic, чтобы избежать условий гонки, сильно зависят от архитектуры). Это не общая библиотека, которая будет компилироваться в любой системе. –  Chris S 27.01.2010 в 06:14
  • @slebetman: После создания потоков ОС будет обрабатывать их так же, как и любой другой поток, неважно, какая библиотека их создала. Таким образом, GCD и Pthreads, однажды созданные, будут работать с одинаковой скоростью. Теперь, если GCD реализует свои собственные мьютексы, они могут быть быстрее или медленнее, чем ручные мьютексы pthread (это будет зависеть в основном от программирования). GCD управляет созданием и отменой потока, поэтому он может или не может представлять собой оптимальное решение; то же самое можно сказать о pthreads, за исключением того, что программист отвечает за создание / отмену с помощью pthreads и может потенциально оптимизировать приложение. –  Chris S 27.01.2010 в 18:57
  • Согласно документации Apple, реальными преимуществами GCD является «управление». Трудно настроить и оптимизировать пул потоков вручную. GCD делает это. И реализация GCD от Apple интегрирована с ядром, а не поверх pthreads. –  Eonil 29.08.2010 в 19:33
Показать остальные комментарии
13

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

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

  • imho, pthread не сложнее , чем GCD: в базовом ядре pthread фактически содержит очень мало команд (только несколько: использование только тех, которые упоминаются в OP, даст вам 95% + функциональности, которая вам когда-либо понадобится). Как и любая библиотека нижнего уровня, это то, как вы объединяете их и как вы используете его, что дает вам силу. Не забывайте, что в конечном итоге библиотеки, такие как GCD и TBB, вызывают библиотеку потоков, например pthreads или std::thread .
  • иногда, это не то, что вы используете, но как вы его используете , что определяет успех и неудачу. Как сторонники библиотеки, TBB или GCD расскажут вам обо всех преимуществах использования их библиотек, но пока вы не попробуете их в реальном контексте приложения, все это имеет теоретическое преимущество . Например, когда я читал о том, как легко было использовать мелкозернистый parallel_for , я сразу использовал его в задаче, для которой, как я думал, может быть полезно параллелизм. Естественно, меня тоже привлек тот факт, что 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 может стоить больше, чем выгоды без серьезной переделки. Также имейте в виду накладные расходы на вызовы функций, такие как lambda через пулы потоков, и использование одного жесткого цикла.

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

    
ответ дан kfmfe04 30.12.2011 в 17:41
источник
4

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

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

    
ответ дан Chris S 27.01.2010 в 05:55
источник
  • Я не слишком заинтересован в кросс-платформенной совместимости. В конце концов, GCD является открытым исходным кодом, и FreeBSD уже приняла его (хотя и в качестве несовершенной реализации). В основном я занимаюсь написанием параллельных программ. Существуют ли случаи, когда параллельный параллельный поток не применим? Меня особенно интересовали конкретные примеры. –  Mike 27.01.2010 в 05:59
  • FreeBSD активно портирует CGD (на самом деле libdispatch, вы не можете «порвать» товарный знак, поскольку это не код). Со стороны компилятора Apple уже отправила исправления в gcc для поддержки синтаксиса закрытия, поддерживающего GCD. –  slebetman 27.01.2010 в 06:01
  • Параллелизм пула потоков отлично подходит для небольших / коротких рабочих нагрузок. Многие веб-серверы построены таким образом, потому что большинство запросов на страницы связаны с минимальной обработкой. Для приложений с различными пользовательскими ролями (например, средства ввода и вывода, а не пользователи-пользователи) для обработки каждого из них могут потребоваться очень разные потоки. Например, ваше приложение может иметь поток управления кэшем диска, поток пользовательских подключений и поток очереди обработки. Это позволит вашей программе воспользоваться преимуществами многоядерных процессоров. Если GCD делает то, что вам нужно, придерживайтесь его, это проще. У Pthreads больше возможностей и сложности –  Chris S 27.01.2010 в 06:07
  • Для вашего примера не было бы более целесообразным использовать прослушиватели событий GCD (с соответствующими файловыми дескрипторами) вместо выделения отдельных потоков? –  Mike 27.01.2010 в 06:11
  • Ну, давайте предположим на мгновение, что вам нужны только три потока, упомянутые в примере. Используя GCD, вы должны иметь обработчик, какой тип функции вы хотите выполнить, а затем вызвать правильную функцию. Также может оказаться интересным внедрение асинхронного ввода-вывода. –  Chris S 27.01.2010 в 06:25
3

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

ответ дан Nikolai Fetissov 27.01.2010 в 06:28
источник
0

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

ответ дан Andy Jackson 23.09.2010 в 21:05
источник
0

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

    
ответ дан ColemanCDA 15.07.2013 в 20:42
источник