Лучший отвечающий
Пул потоков

Вопрос
-
Помогите пожалуйста разобраться.
Создаю приложение
static void Main(string[] args) { for (int i = 0; i < 100; i++) { ThreadPool.QueueUserWorkItem(y => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); for (int j = 0; j < 1000000000; j++) { } } ); } Console.Read(); }
Смысл: хочу запустить 100 потоков для выполнения долгих вычислений. Но когда запускаю вижу, что действующих потоков всего около 5. Хотя Максимально возможное - 1000.
Как мне кажется пул потоков должен выделить (создать если у него нет в наличии) 100 потоков (или чуть меньше), чтобы выполнять работу, но выделяется 5-6 и не более.
Вот привожу результаты расширения sos.dll. Когда я приостанавливаю программу на некотором этапе выполнения:
Вопрос: почему не задействуются максимальное количество потоков?
25 ноября 2013 г. 11:08
Ответы
-
"Допустим если вместо Thread.Sleep у нас будет запрос в бд, логично было бы если все 100 потоков отправят их и будут ждать ответа. Таким образом программа закончится быстрее." - в случае запросов к БД или лругих операций ввода-вывода будут работать I/O Threads (Потоки ввода/вывода), в этом случае они будут созданы.
"Не понимаю по какому принципу пул потоков принимает решение выделять/создавать новый поток или нет" - если речь о вычислительных мощностях, то создавать новые потоки бессмысленно и ухудшает производительность, занимая место в памяти и расходуя время переключения контекста. Поэтому пул на то и пул, чтобы самостоятельно принимать подобные решения. Если хотите подобное, то испльзуйте асинхронные операции, они выделяют I/O треад на операции ввода- вывода (используется пул опять таки).
Сделаем содержимое сообщества лучше, вместе!
- Предложено в качестве ответа Алексей ЛосевEditor 25 ноября 2013 г. 13:20
- Помечено в качестве ответа Higgs.Boson 25 ноября 2013 г. 13:42
25 ноября 2013 г. 13:14Модератор -
Вы ставите Sleep на одном из потоков,
но оставшиеся потоки и плюс еще один или несколько вместо уснувшего потока
все равно полностью загружают процессор.
Здесь имеет смысл только динамика -
каковы наличные ресурсы в данный момент
для открытия дополнительного потока.
Это как в моем примере из предыдущего поста,
каждый из 50-70 потоков ожидает ввода,
поэтому есть смысл организовывать дополнительные потоки.- Помечено в качестве ответа Higgs.Boson 25 ноября 2013 г. 13:43
25 ноября 2013 г. 13:02 -
И в догонку. Вот выдержка из MSDN:
Для увеличения минимального количества потоков можно использовать метод SetMinThreads. Однако необоснованное увеличение этих значений может привести к снижению производительности. Если в одно и то же время запускается слишком много задач, все они могут выполняться слишком медленно. В большинстве случаев пул потоков работает наилучшим образом, используя свой собственный алгоритм распределения потоков.
- Изменено Алексей ЛосевEditor 25 ноября 2013 г. 13:51
- Помечено в качестве ответа Higgs.Boson 25 ноября 2013 г. 13:53
25 ноября 2013 г. 13:50Отвечающий
Все ответы
-
У меня на 2 - ядерном компе эта программа работает в ~ 10 потоках.
Мне кажется, нагрузка слишком велика.
Нет смысла для этой программы создавать дополнительные потоки -
и так процессор загружен под завязку.
Вот если бы здесь перемежались бы какие-либо медленные процессы,
ввод-вывод, например, то было бы иначе.
У меня в таких программах создавалось потоков значительно больше -
до 50 - 70, там это имело смысл.25 ноября 2013 г. 12:05 -
Конечно, Вы правы по поводу того, что я привел беcсмысленный код, который выполняет пустой цикл и грузит процессор. Но это все ради понимания сути.
Даже, если вместо цикла поставить Thread.Sleep(N) (при этом снимется нагрузка с проца, поскольку усыпляю поток) картина не изменится, правда при этом будут активными уже 9-10 потоков.
Вопрос не в том, что мне надо так или не надо. Просто я хочу разобраться, с чем это связанно? По логике вещей, пул потоков должен выделять для новых запросов дополнительные потоки. Если у него нет свободных потоков, то создавать новые. В моем случае, есть 5 активных потоков, которые выполняют все 100 "заявок" на выполнение, но они выполняют их по очередности. Получается, что работа затягивается.
Допустим если вместо Thread.Sleep у нас будет запрос в бд, логично было бы если все 100 потоков отправят их и будут ждать ответа. Таким образом программа закончится быстрее.
Не понимаю по какому принципу пул потоков принимает решение выделять/создавать новый поток или нет
- Изменено Higgs.Boson 25 ноября 2013 г. 12:50 Дополнение
25 ноября 2013 г. 12:49 -
Вы ставите Sleep на одном из потоков,
но оставшиеся потоки и плюс еще один или несколько вместо уснувшего потока
все равно полностью загружают процессор.
Здесь имеет смысл только динамика -
каковы наличные ресурсы в данный момент
для открытия дополнительного потока.
Это как в моем примере из предыдущего поста,
каждый из 50-70 потоков ожидает ввода,
поэтому есть смысл организовывать дополнительные потоки.- Помечено в качестве ответа Higgs.Boson 25 ноября 2013 г. 13:43
25 ноября 2013 г. 13:02 -
Вы ставите Sleep на одном из потоков,
но оставшиеся потоки и плюс еще один или несколько вместо уснувшего потока
все равно полностью загружают процессор.
Здесь имеет смысл только динамика -
каковы наличные ресурсы в данный момент
для открытия дополнительного потока.
Это как в моем примере из предыдущего поста,
каждый из 50-70 потоков ожидает ввода,
поэтому есть смысл организовывать дополнительные потоки.Нет я делаю так (не ставлю на одном потоке, ставлю на каждом)
static void Main(string[] args) { for (int i = 0; i < 100; i++) { ThreadPool.QueueUserWorkItem(y => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); Thread.Sleep(3000); } ); } Console.Read(); }
Я не думаю, что они заняты очень сложными вычислениями. По сути происходит просто вызов и усыпление потоков. Все, для них ОС не выделяет кванты времени.
Только если вместо
Thread.Sleep(3000);
поставить
Thread.Sleep(100000); //100 сек
то он начнет выделять (но очень медленно) дополнительные потоки. Этого можно добиться если сделать
Console.Read()
Видимо, что пул потоков ждет, когда завершения потоков, но так как они не завершаются, ему приходится выделять дополнительные- Изменено Higgs.Boson 25 ноября 2013 г. 13:14
25 ноября 2013 г. 13:08 -
"Допустим если вместо Thread.Sleep у нас будет запрос в бд, логично было бы если все 100 потоков отправят их и будут ждать ответа. Таким образом программа закончится быстрее." - в случае запросов к БД или лругих операций ввода-вывода будут работать I/O Threads (Потоки ввода/вывода), в этом случае они будут созданы.
"Не понимаю по какому принципу пул потоков принимает решение выделять/создавать новый поток или нет" - если речь о вычислительных мощностях, то создавать новые потоки бессмысленно и ухудшает производительность, занимая место в памяти и расходуя время переключения контекста. Поэтому пул на то и пул, чтобы самостоятельно принимать подобные решения. Если хотите подобное, то испльзуйте асинхронные операции, они выделяют I/O треад на операции ввода- вывода (используется пул опять таки).
Сделаем содержимое сообщества лучше, вместе!
- Предложено в качестве ответа Алексей ЛосевEditor 25 ноября 2013 г. 13:20
- Помечено в качестве ответа Higgs.Boson 25 ноября 2013 г. 13:42
25 ноября 2013 г. 13:14Модератор -
Вот тут я не знаю,
насколько Sleep освобождает ресурсы,
и освобождает ли.25 ноября 2013 г. 13:24 -
"Допустим если вместо Thread.Sleep у нас будет запрос в бд, логично было бы если все 100 потоков отправят их и будут ждать ответа. Таким образом программа закончится быстрее." - в случае запросов к БД или лругих операций ввода-вывода будут работать I/O Threads (Потоки ввода/вывода), в этом случае они будут созданы.
"Не понимаю по какому принципу пул потоков принимает решение выделять/создавать новый поток или нет" - если речь о вычислительных мощностях, то создавать новые потоки бессмысленно и ухудшает производительность, занимая место в памяти и расходуя время переключения контекста. Поэтому пул на то и пул, чтобы самостоятельно принимать подобные решения. Если хотите подобное, то испльзуйте асинхронные операции, они выделяют I/O треад на операции ввода- вывода (используется пул опять таки).
Сделаем содержимое сообщества лучше, вместе!
25 ноября 2013 г. 13:26 -
Он не освобождает, а блокирует поток, что с точки зрения производительности плохо, так как происходит переключение контекста.
Сделаем содержимое сообщества лучше, вместе!
25 ноября 2013 г. 13:27Модератор -
Вы привели пример, который не отражает Вашей реальной задачи.
Нужно для тестирования применять более реальные примеры.25 ноября 2013 г. 13:32 -
Он не освобождает, а блокирует поток, что с точки зрения производительности плохо, так как происходит переключение контекста.
А Thread.Sleep не вызывает внутри себя Win32 Sleep? Просто мне не понятно, почему при этом ОС продолжает выделять ему процессорное время?
Сделаем содержимое сообщества лучше, вместе!
25 ноября 2013 г. 13:33 -
Вы привели пример, который не отражает Вашей реальной задачи.
Нет никакой задачи))) Разбираю теорию)
Нужно для тестирования применять более реальные примеры.25 ноября 2013 г. 13:35 -
Это понятно.
Но в этом примере все процессорные ресурсы забиты до отказа,
и никаких дополнительных потоков не нужно,
поскольку дополнительные потоки -
это дополнительные накладные расходы.
Система разумна.
Но если Вам нужно обращаться к БД с тысячью запросами одновременно,
то нужно и тест спроектировать подобно заданию.- Изменено QazRdx 25 ноября 2013 г. 13:42
25 ноября 2013 г. 13:42 -
Хорошо. Спасибо за ответы!)25 ноября 2013 г. 13:42
-
Читайте последнее издание Рихтера,там все по полочкам изложено.
Сделаем содержимое сообщества лучше, вместе!
25 ноября 2013 г. 13:42Модератор -
Читайте последнее издание Рихтера,там все по полочкам изложено.
Сделаем содержимое сообщества лучше, вместе!
Я как раз вот и читаю его) Он говорит что таким образом он на своей машине запускал 4 млн одновременных запросов, я вот поэтому и спрашиваю как сделать так чтобы пул выделил максимальное количество потоков сразу.
А еще он говорит там, что в веб-приложениях тоже пул-потоков реализован. Вот мне интересно, там класс poolThread используется, или что-то другое?
- Изменено Higgs.Boson 25 ноября 2013 г. 13:47
25 ноября 2013 г. 13:45 -
Еще раз. Есть куча способов создать отдельный поток: Thread, Task, async/await и т.д. Есть некие знания программистов Microsoft, которые реализовались в механизме ThreadPool. Чем они руководствовались? Я очень сильно подозреваю, что вам никто не подскажет. Вот есть такой механизм. Он работает так как работает. Вы его применяете в реальной задаче. Смотрите. Вас что то не устраивает. Вы переписываете на свою модель управления потоками. Смотрите. Вас не устраивает. Еще раз переписываете. В результате вы получите модель которая будет работать в вашем, конкретном случае лучше, чем ThreadPool, либо... что тоже вероятно, возвратитесь на ThreadPool.25 ноября 2013 г. 13:48Отвечающий
-
И в догонку. Вот выдержка из MSDN:
Для увеличения минимального количества потоков можно использовать метод SetMinThreads. Однако необоснованное увеличение этих значений может привести к снижению производительности. Если в одно и то же время запускается слишком много задач, все они могут выполняться слишком медленно. В большинстве случаев пул потоков работает наилучшим образом, используя свой собственный алгоритм распределения потоков.
- Изменено Алексей ЛосевEditor 25 ноября 2013 г. 13:51
- Помечено в качестве ответа Higgs.Boson 25 ноября 2013 г. 13:53
25 ноября 2013 г. 13:50Отвечающий -
И в догонку. Вот выдержка из MSDN:
Для увеличения минимального количества потоков можно использовать метод SetMinThreads. Однако необоснованное увеличение этих значений может привести к снижению производительности. Если в одно и то же время запускается слишком много задач, все они могут выполняться слишком медленно. В большинстве случаев пул потоков работает наилучшим образом, используя свой собственный алгоритм распределения потоков.
да, при установке например ThreadPool.SetMinThreads(1000, 1000); запущенное приложение выполняется меньше секунды. но к сожалению выделяет 1000 потоков) что не есть хорошо.
25 ноября 2013 г. 13:54 -
Все-таки такое поведение не исправишь. Спасибо всем тем кто откликнулся и поделился знаниями или мнением. Вопрос можно считать закрытым)25 ноября 2013 г. 13:55
-
Вот еще один полезный пример -
http://social.msdn.microsoft.com/Forums/ru-RU/06a9edd2-d9b0-4508-8069-6e2b49d901d4/linq-?forum=programminglanguageru28 декабря 2013 г. 17:17