Почему потоки ОС считаются дорогими? - PullRequest
25 голосов
/ 01 апреля 2012

Существует множество решений, направленных на реализацию потоков в пользовательском пространстве.Будь то gorang.org goroutines, зеленые потоки python, асинхронность C #, процессы erlang и т. Д. Идея состоит в том, чтобы разрешить параллельное программирование даже с одним или ограниченным числом потоков.

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

ОС предоставляет обе эти функции бесплатно.Почему потоки ОС должны быть дороже, чем «зеленые» потоки?В чем причина предполагаемого снижения производительности, вызванного выделением потока ОС для каждой «задачи»?

Ответы [ 6 ]

13 голосов
/ 01 апреля 2012

Я хочу изменить ответ Тюдоров, который является хорошей отправной точкой.Существуют две основные накладные расходы потоков:

  1. Запуск и остановка их.Включает создание стека и объектов ядра.Включает в себя переходы ядра и глобальные блокировки ядра.
  2. Сохранение их стека.

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

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

6 голосов
/ 01 апреля 2012

Сохранение стека тривиально, независимо от его размера - указатель стека необходимо сохранить в блоке Thread Info в ядре (поэтому обычно сохраняется большинство регистров, так как они будут выталкиваться любым программным обеспечением)./ жесткое прерывание вызвало ввод ОС).

Одна из проблем заключается в том, что для входа в ядро ​​от пользователя требуется цикл защиты уровня.Это существенно, но раздражает, накладные расходы.Затем драйвер или системный вызов должен делать все, что было запрошено прерыванием, а затем планировать / распределять потоки на процессоры.Если это приводит к вытеснению потока из одного процесса потоком из другого, загрузка дополнительного контекста процесса также должна быть заменена.Еще больше накладных расходов добавляется, если ОС решает, что поток, работающий на другом ядре процессора, будет прерван, а другое ядро ​​должно быть прервано аппаратно (это поверх жесткого / программного прерывания, котороеВо-первых, это операционная система.

Итак, планирование может быть довольно сложной операцией.

«Зеленые потоки» или «волокна» (обычно) запланированы из кода пользователя. Изменение контекста намного проще и дешевле, чем прерывание ОС и т. Д., Поскольку при каждом изменении контекста не требуется цикл Вагнера по кольцу, контекст процесса не изменяется, а поток ОС, выполняющий зеленую группу потоков, не изменяется.

Поскольку чего-то бесполезного не существует, существуют проблемы с зелеными потоками. Они запускаются «реальными» потоками ОС. Это означает, что если один «зеленый» поток в группе, запущенной одним потоком ОС, создаетвызов ОС, который блокирует, все зеленые потоки в группе заблокированы. Это означает, что простые вызовы, такие как sleep (), должны быть emuзаполняется 'конечным автоматом, который уступает другим зеленым потокам (да, точно так же, как повторная реализация ОС).Точно так же любая межпотоковая сигнализация.

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

6 голосов
/ 01 апреля 2012

Существует множество решений, направленных на реализацию потоков в пользовательском пространстве.Будь то gorang.org goroutines, зеленые потоки python, асинхронность C #, процессы erlang и т. Д. Идея состоит в том, чтобы позволить параллельное программирование даже с одним или ограниченным числом потоков.

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

Чего я не понимаю, так это то, почему потоки ОС так дороги?На мой взгляд, в любом случае вам нужно сохранить стек задачи (поток ОС или поток пользовательского пространства), который составляет несколько десятков килобайт, и вам нужен планировщик для перемещения между двумя задачами.

Создание потока стоит дорого, а стеку требуется память.Кроме того, если ваш процесс использует много потоков, переключение контекста может снизить производительность.Таким образом, легкие модели потоков стали полезными по ряду причин.Создание потока ОС стало хорошим решением для средних и больших задач, в идеале в небольших количествах.Это ограничительно и требует много времени для обслуживания.

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

Более общеизвестно (IMO), потоки уровня ОС дороги, потому что онине используются корректно инженерами - либо их слишком много, либо переключение контекста на тонну, либо конкуренция за тот же набор ресурсов, либо задачи слишком малы.Требуется намного больше времени, чтобы понять, как правильно использовать потоки ОС и как наилучшим образом применять их в контексте выполнения программы.

ОС предоставляет обе эти функции бесплатно.

Они доступны, но они не бесплатны.Они сложны и очень важны для хорошей производительности.Когда вы создаете поток ОС, ему дается время «скоро» - все время процесса делится между потоками.Это не частый случай с пользовательскими потоками.Задача часто ставится в очередь, когда ресурс недоступен.Это уменьшает переключение контекста, память и общее количество потоков, которые должны быть созданы.Когда задача завершается, поток получает другой.

Рассмотрим эту аналогию распределения времени:

  • Предположим, вы находитесь в казино.Есть ряд людей, которым нужны карты.
  • У вас есть фиксированное количество дилеров.Дилеров меньше, чем людей, которым нужны карты.
  • Не всегда достаточно карт для каждого человека в любой момент времени.
  • Людям нужны все карты для завершения своей игры / руки.Они возвращают свои карты дилеру, когда их игра / рука завершена.

Как бы вы попросили дилеров раздавать карты?

В планировщике ОС это будет основано на(поток) приоритет.Каждому человеку будет даваться одна карта за раз (время ЦП), и приоритет будет оцениваться непрерывно.

Люди представляют задачу или работу потока.Карты представляют время и ресурсы.Дилеры представляют темы и ресурсы.

Как бы вы справились быстрее, если бы было 2 дилера и 3 человека?а если было 5 дилеров и 500 человек?Как вы могли бы минимизировать нехватку карт для раздачи?С помощью потоков добавление карт и добавление дилеров - это не решение, которое вы можете предложить «по требованию».Добавление процессоров эквивалентно добавлению дилеров.Добавление потоков эквивалентно тому, что дилеры раздают карты одновременно большему количеству людей (увеличивает переключение контекста).Существует ряд стратегий для более быстрого раздачи карт, особенно после того, как вы избавитесь от потребности людей в картах за определенное время.Разве не было бы быстрее подойти к столу и заключить сделку с человеком или людьми, пока их игра не будет завершена, если соотношение дилера и людей будет 1/50?Сравните это с посещением каждой таблицы в зависимости от приоритета и координацией посещения всех дилеров (подход ОС).Это не означает, что ОС глупа - это означает, что создание потока ОС - это инженер, добавляющий больше людей и больше таблиц, потенциально больше, чем разумно могут обработать дилеры.К счастью, ограничения могут быть сняты во многих случаях с помощью других моделей многопоточности и более высоких абстракций.

Почему потоки ОС должны быть дороже, чем "зеленые" потоки?В чем причина предполагаемого снижения производительности, связанного с выделением отдельного потока ОС для каждой «задачи»?

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

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

4 голосов
/ 01 апреля 2012

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

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

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

Одна вещь, которая делает «зеленым»потоки быстрее, чем потоки ядра, состоят в том, что они являются объектами пользовательского пространства, управляемыми виртуальной машиной.Запуск их - это вызов пространства пользователя, а запуск потока - вызов пространства ядра, который намного медленнее.

2 голосов
/ 14 ноября 2013

Человек в Google демонстрирует интересный подход.

По его словам, переключение режимов ядра само по себе не является узким местом, и затраты на ядро ​​происходят в планировщике SMP.И он утверждает, что расписание M: N с помощью ядра не будет дорогим, и это заставляет меня ожидать, что общие потоки M: N будут доступны на всех языках.

0 голосов
/ 01 апреля 2012

Я думаю, что две вещи находятся на разных уровнях.

Thread или Process - это экземпляр программы, которая выполняется.В процессе / потоке гораздо больше вещей.Стек выполнения, открытие файлов, сигналы, состояние процессоров и многое другое.

Greentlet отличается, он работает в VM.Это поставляет легкую нить.Многие из них предоставляют псевдо-одновременно (обычно в одном или нескольких потоках уровня ОС).И часто они предоставляют метод без блокировки при передаче данных вместо обмена данными.

Итак, две вещи фокусируются по-разному, поэтому вес различен.

И, на мой взгляд, гринлет должен быть закончен в ВМ, а не в ОС.

...