Я устал слышать, как люди рекомендуют использовать только один поток на процессор, в то время как многие программы используют до 100 на процесс! возьмем для примера некоторые распространенные программы
vb.net ide uses about 25 thread when not debugging
System uses about 100
chrome uses about 19
Avira uses more than about 50
Каждый раз, когда я публикую вопрос, связанный с темой, мне почти каждый раз напоминают, что мне не следует использовать более одного потока на процессор, и все программы, о которых я упоминал выше, разрушаются в моей системе с одним процессором.
Ответы:
Возможно, в HPC, где вы хотите максимальной эффективности - но в остальном самая глупая вещь, которую я слышал сегодня!
Вы должны использовать количество потоков, которые соответствуют дизайну программы и все же дают приемлемую производительность.
Для веб-сервера может быть целесообразно запускать поток для каждого входящего соединения (хотя существуют и более эффективные способы для сильно загруженных серверов).
В идеале каждый инструмент, работающий в своем собственном потоке, не является необоснованным. Я подозреваю, что многие потоки, сообщенные для .Net IDE, - это такие вещи, как ведение журнала и задачи ввода-вывода, запускаемые в своих собственных потоках, чтобы они могли продолжать разблокироваться.
источник
Рекомендация «один поток на ядро» применяется, когда целью является скорость посредством параллельного выполнения.
Совершенно другая и в равной степени обоснованная причина - простота кода, когда он должен реагировать на непредсказуемые события. Так что, если программа должна прослушивать 100 сокетов и, по-видимому, уделять все свое внимание каждому из них, это идеальное применение для многопоточности. Другим примером является пользовательский интерфейс, где один поток обрабатывает события пользовательского интерфейса, а другой - фоновую обработку.
источник
Вам нужен один поток для каждого вычисления, которое может выполняться с различной скоростью, чем другие вычисления.
Для параллельных вычислений с привязкой к ЦП, которые занимают большие блоки, обычно требуется один поток на ЦП, поскольку, когда все они заняты, больше потоков не помогают и просто создают накладные расходы планировщика. Если блоки работы имеют нерегулярные размеры во времени или генерируются динамически во время выполнения (часто это происходит при обработке больших сложных структур данных), вам может потребоваться присоединить эти блоки к множеству потоков, поэтому у планировщика всегда есть большой выберите, когда какой-либо блок работы завершится, чтобы все процессоры были заняты.
Для вычислений, связанных с вводом / выводом, обычно требуется один поток для каждого независимого «канала» ввода / вывода, поскольку они обмениваются данными с разными скоростями, а потоки, заблокированные на канале, не препятствуют продвижению других потоков.
источник
Эмпирическое правило для потоков заключается в том, что для каждого «исполнительного блока», доступного на компьютере, требуется по крайней мере один «активный» (способный выполнять свои команды немедленно при заданном времени процессора). «Исполнительный блок» - это один процессор логических команд, поэтому четырехъядерный четырехъядерный гиперпоточный сервер Xeon будет иметь 32 EU (4 микросхемы, 4 ядра на микросхему, каждая гиперзаходная). Ваш средний Core i7 будет иметь 8.
Один поток в ЕС - это наиболее полное использование мощности процессора при условии, что потоки всегда будут в рабочем состоянии; это почти никогда не происходит, поскольку потокам необходим доступ к некешированной памяти, жесткому диску, сетевым портам и т. д., которых они должны ждать, и которые не требуют активного внимания ЦП для выполнения. Таким образом, вы можете еще больше повысить общую эффективность, добавив больше потоков в очередь и рваясь в путь. Это действительно стоит денег; когда ЦП переключает поток, он должен кэшировать регистры потока, указатель выполнения и другую информацию о состоянии, которая обычно хранится во внутренних документах ЕС и очень быстро доступна, что позволяет другим ЕС в этом чипе ЦП забрать его. Также требуется, чтобы потоки в ОС решали, на какой поток следует переключиться. Наконец, когда ЕС переключает темы, он теряет прирост производительности конвейерной обработки, которую использует большинство процессорных архитектур; он должен промыть конвейер перед переключением потоков. Но, поскольку все это в среднем занимает гораздо меньше времени, чем простое ожидание, пока жесткий диск или даже ОЗУ не вернутся с информацией, это стоит затрат.
Тем не менее, как правило, когда вы вдвое превышаете число «активных» потоков по сравнению с ЕС, ОС начинает тратить больше потоков планирования времени ЕС, а ЕС тратит больше времени на переключение между ними, чем фактически тратит на запуск активных потоков. программ. Это точка диссоциации масштаба; на самом деле многопоточный алгоритм будет работать дольше, если в этот момент вы добавите дополнительный поток.
Итак, в целом, вы хотите сохранить как минимум столько потоков в вашей программе, сколько у вас есть EU на компьютере, но вы хотите избежать более чем удвоения этого числа, которое не ждет или не спит.
источник
Вы должны использовать один поток для:
Каждый процессор нужно держать занятым.
Каждый ввод / вывод, который вы можете одновременно использовать, не может быть выполнен неблокирующим. (Например, читает с локального диска.)
Каждая задача, для которой требуется выделенный поток, например, вызов библиотеки, у которой нет неблокирующего интерфейса или где неблокирующие интерфейсы не подходят. Это включает в себя такие задачи, как мониторинг системных часов, таймеры включения и так далее.
Несколько дополнительных для защиты от неожиданных блокировок, таких как сбои страниц.
Несколько дополнительных для защиты от ожидаемой блокировки, которую не стоит оптимизировать, например, в некритическом коде. (Например, если вам может понадобиться выполнить запрос DNS очень редко, возможно, не стоит делать запросы DNS асинхронно. Просто создайте несколько дополнительных потоков и упростите свою жизнь.)
Если вы следуете правилу «один поток на процессор», то весь ваш код критичен к производительности. Любой код, который по какой-то причине блокирует, означает, что ваш процесс не может использовать этот процессор. Это делает программирование намного сложнее без веской причины.
источник
Вы можете либо порождать процессы и потоки, чтобы разрешить использование многоядерной \ многопроцессорной системы для одной программы, и в этом случае вы не получите никакой выгоды (по крайней мере, для одной программы), имея больше потоков \ процессов, чем ядер.
Или вы можете иметь подпрограммы, которые опрашивают событие, которое обычно блокирует дальнейшее выполнение. Вместо того, чтобы связать процессор с опросом, вы можете вместо этого создать поток, который будет находиться в состоянии ожидания до тех пор, пока его не разбудит соответствующее событие. Этот метод очень часто используется на веб-серверах и в очередях событий графического интерфейса. Большинство программ хотят иметь какое-то центральное хранилище данных (даже если это код выполнения программы), к которому могут обращаться все потоки, поэтому я думаю, именно поэтому они используют потоки над процессами.
источник
Приложения, которые вы упоминаете, редко запускают все эти десятки потоков одновременно. Большинство из них просто сидят там, потому что они находятся в пуле потоков . Приложение отправляет различные задачи в очередь, которая очищается потоками в пуле потоков.
Почему размер бассейна такой большой? Потому что часто потокам приходится ждать других ресурсов, таких как диск, сеть, пользователь, какой-то другой поток и т. Д. Пока поток ожидает, целесообразно запустить другие потоки, чтобы полностью использовать процессор. Однако правильно подобрать размер пула сложно. Слишком мало потоков, и вы потеряете производительность, потому что процессор не используется полностью, ожидая чего-то. Слишком много потоков, и вы потеряете производительность из-за переключения между ними.
источник