Boost thread - ограниченное количество потоков?, непонятное ограничение, не связанное с ресурсами системы |
Здравствуйте, гость ( Вход | Регистрация )
Boost thread - ограниченное количество потоков?, непонятное ограничение, не связанное с ресурсами системы |
Iron Bug |
6.2.2009, 11:23
Сообщение
#1
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
добрый день всем.
вот, может, кто сталкивался с подобной проблемой: использую библиотеку thread boost'а для кроссплатформенного программирования. до недавего времени всё было замечательно, но тут возникло одно неприятное открытие: оказалось, что буст почему-то ограничивает возможное количество потоков. а именно: после создания какого-то числа работающих потоков создание очередного потока проваливается с исключением boost::thread_resource_error и до уменьшения количества работающих потоков создание нового потока невозможно (каждый раз выпадает это исключение). причём это максимальное число потоков не зависит от реальных ресурсов системы, либо зависимость мне непонятна. для проверки была написана маленькая программа - генератор потоков. потоки просто создаются, спят какое-то время, потом завершаются. потоки пустые, мелкие - то есть, памяти теоретически должно хватать. при этом задавалось разное время жизни потоков и разное количество потоков. результаты по подсчёту количества потоков всегда одинаковы, независимо от времени жизни каждого потока. это число каким-то загадочным образом зависит от машины, но, по видимому, не зависит от количества свободной памяти процесса и системы. из опытов получилась такая странная картина: дома стоит машина под линюксом, 4 гектара памяти, своп вообще не используется - опытным путём получен предел в 382 потока, на работе машина под вендой, 1 гектар памяти, предел - 2024 потока. увеличение-уменьшение количества других процессов в системе никак не влияет. откуда берутся такие странные цифры? может, есть возможность определить каким-то образом, как распределять ресурсы, чтобы потоков было больше? по работе необходима возможность одновоеменного выполнения очень большого и заранее неопределённого количества потоков в риал-тайме (пул потоков как бы не подходит по замыслу задачи). непонятно, откуда исходит это ограничение и как с ним бороться (если это вообще возможно). |
|
|
ViGOur |
6.2.2009, 11:33
Сообщение
#2
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Все правильно, это ограничение потоков, для винды это выставляется в реестре.
Цитата Какие существуют ограничения на количество потоков в программе? Разумно предположить, что количество потоков в процессе ограничено ресурсами самого процесса, а так же ресурсами ядра операционной системы. ПРИМЕЧАНИЕ Все сказанное ниже справедливо для линейки Windows NT/2000/XP. Один из основных ресурсов ядра операционной системы, потребляемый при создании потока, это невыгружаемая памяти (non-paged memory) ядра. Создание одного потока требует около 12 килобайт невыгружаемой памяти. Ограничения на размер пула невыгружаемой памяти устанавливается в следующем ключе системного реестра: HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management параметрами NonPagedPoolQuota и NonPagedPoolSize. Их значение по умолчанию равно нулю, что отдает управление этими значениями в руки операционной системы. То есть при современных объемах памяти крайне сложно выбрать все ресурсы ядра операционной системы, создавая большое количество потоков. Остаются только ресурсы процесса, о чем мы и поговорим подробнее. Как известно, каждому процессу выделяется адресное пространство в четыре гигабайта, но под свои нужды процесс может употребить только первые два гигабайта. Собственно из этих двух гигабайт и выделяется память под стек для вновь создаваемого потока. Размер стека определяется двумя факторами - параметром /STACK линковщика и параметром dwStackSize функции CreateThread. Размер стека, заданный параметром dwStackSize, не может быть меньше, чем указано в параметре /STACK линковщика и по умолчанию равен ему. Размер стека, используемый линковщиком по умолчанию равен одному мегабайту. Таким образом максимальное количество потоков, которые можно создать при всех параметрах заданных по умолчанию, равняется примерно 2035. По достижении этого предела функция CreateThread начинает возвращать ошибку ERROR_NOT_ENOUGH_MEMORY, что является истинной правдой - если умножить количество потоков на размер стека по умолчанию, то как раз получается примерно два гигабайта - размер адресного пространства отданный процессу на карманные расходы. Обойти это ограничение можно указав меньший размер стека параметром /STACK линковщика или в Project Settings (Link/Output/Stack Allocations/Reserve) в Microsoft Visual C++. Размер стека указывается в байтах. Меняя это значение надо быть осторожным ввиду того, что стек используется не только для хранения адресов возврата функций и передачи параметров, но и для хранения локальных переменных. Однако это тема отдельного разговора. Для линукса также можно настроить это дело, но как не знаю. |
|
|
Iron Bug |
6.2.2009, 11:45
Сообщение
#3
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
да сомневаюсь я, что это ограничение по памяти. в моих опытах все ресурсы процесса по пику использования памяти были не больше 60 метров, судя по показаниям диспетчера задач... то есть, до 4 гигов как до луны! можно, кстати, при этом динамически выделять массивы - никаких ошибок не происходит.
у меня подозрение, что тут какая-то хитрость в самом бусте... может, дефайны какие-то надо выставлять ему, чтобы юзал больше ресурсов или что-то подобное. но в документации ничего нет про это. со стеком в венде настройки попробую поковырять. результаты сообщу. |
|
|
Litkevich Yuriy |
6.2.2009, 11:50
Сообщение
#4
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
что это ограничение по памяти. я где-то напарывался на обсуждение про ограничение числа потоков, речь шла не о Бусте, но вывод был такой: Есть умалчиваемые настройки ОСи (и линя и виндовоза), которые не позволяют одному экземпляру приложения полдить потоки больше определенного потолка.Так что я думаю ViGOur, правильную статью показал. |
|
|
ViGOur |
6.2.2009, 11:52
Сообщение
#5
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Цитата, которую я привел справедлива для Win32 Api и его CreateThread и прочего отстраненно от boost'a. Так что boost тут не причем.
Все зависит от опреционки и ее настроек. |
|
|
Iron Bug |
6.2.2009, 11:56
Сообщение
#6
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
пока что происходят странные вещи: при УВЕЛИЧЕНИИ размера стека (под вендой) максимальное количество потоков.... УМЕНЬШАЕТСЯ!!! причём пропорционально: в два раза увеличиваю стек - в два раза меньше потоков можно запустить одновременно, в два раза уменьшаю - в два раза больше потоков можно удачно запустить...
вот так... наблюдаю и думаю.... понять сего явления пока не могу как математик, могу теоретически предположить, что при уменьшении размера стека до нуля количество потоков приблизится к идеально неограниченному |
|
|
Litkevich Yuriy |
6.2.2009, 12:04
Сообщение
#7
|
разработчик РЭА Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: 94 |
|
|
|
Iron Bug |
6.2.2009, 12:41
Сообщение
#8
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
дык вот не смешно совсем. пока в песочнице копошишся - всё отлично. а как начинаешь вылазить за пределы обычного десктопного софта - так сразу обнаруживаются всякие тонкости, которые нигде не описаны в документации, либо описаны крайне поверхностно и туманно.
пока что результаты экспериментов в венде: 1. размер стека (параметр линковки) влияет на количество потоков в обратной пропорции. это мне теперь стало понятно: на каждый поток выделяется стек из пула. соответственно, меньше стек - больше потоков. но вот уменьшать размер стека как бы не очень хотелось бы... не то, чтобы дочерние потоки какие-то монстрообразные вглубь и вширь... они, как правило, очень простые и часто даже линейные, но всё же стек есть стек. 2. размер кучи (параметр линковки) не влияет никак 3. размер NonPagedPoolQuota в реестре (вроде как у майкрософта написано, что это есть пул для потока), поставленный в максимум=128 (это число было взято с сайта майкрософта), после перезагрузки машины не дал никакого результата. думаю, общий NonPagedPoolSize (суммарный пул для системы) менять не имеет смысла - ведь остальные приложения жрут и поболе памяти и в сумме при высокой нагрузке на систему венда вполне нормально использует всю память. у меня вообще нет подозрений на нехватку пула. какие-то 60 метров - это вообще пустяки для системы. очевидно, система просто рассчитывает максимальное количество потоков исходя из размера стека и возможности адресации 2 гигов на процесс и на этом всё, и ничего тут не изменить... про линюкс пока туман. буду копать ещё и ставить эксперименты дома. |
|
|
ViGOur |
6.2.2009, 13:00
Сообщение
#9
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Как решишь проблему опиши как решил, а то больно интересная тема!
|
|
|
some_x |
22.2.2009, 0:00
Сообщение
#10
|
Новичок Группа: Новичок Сообщений: 1 Регистрация: 21.2.2009 Пользователь №: 570 Спасибо сказали: 0 раз(а) Репутация: 0 |
добрый день всем. вот, может, кто сталкивался с подобной проблемой: Я провёл исследования на линуксе используя pthread(увеорен boost.thread на линухе реализован через него). Действительно со стандартным размером стэка(а это, как выяснилось 8-мь мегабайт) можно создать где-ьл 382 нити. При стэке более 2.5 гигабайт не удаётся создать ни одной нити(ошибка ENOMEM). Проверил на машине с 2 гигабайтами памяти и с одним, граница не изменилась. При указании размера стека 4096*1024*1024 байт получил ошибку: некорректное значение стэка. При стэке размером в 1 гигабайт удавалось создать не более двух нитей. Таким образом можно сделать вывод что в линуксе(если используется nptl) суммарный размер стэка создаваемых нитей должен быть не больше 2.5 гигабайт(примерно), хотя возможно какие-то системные твики могут это изменить. |
|
|
Текстовая версия | Сейчас: 26.11.2024, 6:14 |