2015-07-09 3 views
3

Я только начал работать с потоками и быстро пришел к самому распространенному вопросу о том, сколько потоков слишком много?
После некоторых исследований я еще больше смутился.C# Максимальное количество потоков

задача
У меня есть 16 ядер и приложение генерации 1000 объектов, будучи несмотря от строительных параметров в соответствии. Создание 1000 потоков обычно создавало бы огромные накладные расходы, разрушающие преимущества производительности от многопоточности в соответствии с документацией msdn и Maximum number of threads. Также я должен оставаться в пределе 3.5 NET 32 бит (Maximum number of threads in a .NET app?).

Вопрос 1
Имея такую ​​одностороннюю задачу, можно создать больше потоков, чем ядер на компьютере? Оптимизирует ли .NET что-то там? Каково максимальное количество потоков, которые я должен использовать?

Вопрос 2
Есть простое красивое решение, другой затем очереди его с предельными ресурсами? Что-то вроде семафора, где я создаю все 1000 потоков, но сразу же инактивирует потоки, чтобы не выделять стек потоков по умолчанию?

+3

Пул потоков - полезная концепция. –

+4

Вы не должны создавать столько потоков, создавать столько потоков, сколько количество ядер и повторно использовать поток для выполнения нескольких задач. – Marko

+4

Отсутствует в вашем вопросе то, что вы думаете о потоке. Почему, по вашему мнению, вам нужно 1000 потоков для создания 1000 объектов? – CodeCaster

ответ

5

Да, вы можете (и, вероятно, должны) создать больше потоков, чем есть ядра, так как операционная система планировщик будет ПРЕРЫВАЙТЕ поменять среди активных потоков, даже если ничего не ждет от этого ядра. Однако вы также не хотите создавать 1000 отдельных потоков. Вместо этого создайте несколько потоков и разделите их между ними, чтобы каждый поток обрабатывал более одного элемента из полного задания.

Я нашел, что хорошим правилом является переход на два потока на каждое логическое ядро ​​(это считается гиперпотоковыми ядрами ... если у вас есть 8-ядерный процессор с гиперпотоком для 16 логических ядер, создайте 32 потоки). Идея заключается в том, что вы хотите как можно меньше перехватчиков планировщика/контекстных свопов, но в то же время держите все ядра занятыми, работая в основном на вашей задаче. При этом возникают ошибки, связанные с переполнением планировщика :, даже если в логическом ядре ничего больше не активно, причем два активных потока для этого ядра означают, что планировщик может просто вставить простаивающий поток из вашей программы. Даже если другие вещи активны для этого ядра, теперь все еще вероятно, что ваш поток выбран для выполнения. Выше, чем это, может стимулировать больше переключателей контекста, чем это необходимо, и ухудшать производительность.

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

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

Наконец, в мире .Net стоит упомянуть ThreadPool и async Tasks. Это не лучшее место, чтобы попасть в полный учебник по этим предметам, но чтение на них хорошо стоит вашего времени.

1

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

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

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

Ответ 1: Да, возможно создать больше потоков, чем ядер, но это делает нулевой смысл.

Ответ 2: Не создавайте 1000 потоков для создания 1000 объектов! это не красиво

3

Возможно ли создать больше потоков, чем ядра на компьютере?

Да, это возможно.

Является ли .NET оптимизацией чего-то там? Каково максимальное количество потоков, которые я должен использовать?

На самом деле вам не нужно заботиться о количестве потоков в 99,99% случаев, потому что вы ... не должны создавать потоки вручную в 99,99% случаев. Вместо этого используйте ThreadPool, если вы должны оставаться в пределах .NET 3.5. Используйте tasks, если ваша версия 4.0 или выше.

Есть ли простое красивое решение, другое, а затем его очереди с ограниченными ресурсами?

Фактически, нет. Вы не можете перепрыгнуть через физически доступные ресурсы, это бутылочная шее.

Смежные вопросы