Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 14, 2010 18:58:31

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Проблемы с рекурсией

Сейчас будет много теории - а потом варианты решения.
Стек - непрерывная область памяти (в виртуальной адресации, разумеется).
Резервируется окно и в нем сверху выделяется кусок памяти.
По умолчанию на винде это выглядит так: ]
Размер стека потока должен быть указан до запуска этого самого потока, естественно.
Также очевидно, что готовый стек уже нельзя перенести в другое место - в нем записаны абсолютные адреса, перенос все ломает.
В общем случае стек еще и нельзя расширить - место за границами окна может быть занято.
Т.е. стек - это навсегда, пока поток не помрет.
Почему нельзя резервировать сразу очень много? Да потому, что объем виртуальной (адресуемой) памяти - конечен.
На Windows 32 bit это 2 гигабайта. Каждый поток ест по крайней мере 2 мегабайта на свой стек. Результат - невозможно запустить больше тысячи потоков.
На практике это число еще меньше.

Далее. Максимальный размер стека можно указать перед запуском потока - есть такой параметр у CreateThread.
Но для нового процесса размер стека для главного потока указать нельзя - CreateProcess о таком не заботится.
В linux есть ulimit, в Windows - ничего. А после запуска процесса (нашего питона, например) уже ничего поменять нельзя - поток стартовал, поезд ушел.

Но способ регулировки есть. В заголовках образа (exe файла, если по простому) есть параметр, указывающий размер зарезервированного стека.
Запускаем cmd.exe
cd “C:\Program Files\Microsoft Visual Studio 9.0\VC\”
vcvarsall.bat
cd bin
dumpbin.exe /HEADERS c:\Python27\python.exe

Выводит длинную простыню. Во втором заголовке (OPTIONAL HEADER VALUES) находим 1E8480 size of stack reserve. Это наши 2 мегабайта.

Увеличим вдвое:
editbin.exe /STACK:4000000 c:\Python27\python.exe

Через dumpbin можно проверить результат.

Выглядит кривовато - да так оно и есть. Не трогая питон - стек не увеличишь.

Есть еще один вариант. Сделать свой exe - запускатель интерпретатора (это несложно) и в нем указать желаемый размер стека.
Или запаковать все py2exe - а дальше вы поняли. Можно и py2exe поправить, чтобы размер сразу нужный был.

Главный вывод - не трогая запускаемый файл - стек не увеличишь (для главного потока).

Для потоков, созданных из питона можно перед запуском потока вызвать threading.stack_size
Только помните - размеры стеков станут разными. А это тоже неудобно и выглядит опять таки хаком.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version