Для чего мне использовать Stackless Python? - PullRequest
42 голосов
/ 08 февраля 2010

Есть много вопросов, связанных со Stackless Python. Но никто не отвечает на этот мой вопрос, я думаю (поправьте меня, если не прав - пожалуйста!). Все это время что-то жужжит, поэтому мне интересно знать. Для чего мне использовать Stackless? Чем он лучше CPython?

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

Ответы [ 6 ]

30 голосов
/ 12 февраля 2010

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

Эта статья тестирует именно это, создавая сто тысяч тасклетов в Python и Google Go (новый язык программирования): http://dalkescientific.com/writings/diary/archive/2009/11/15/100000_tasklets.html

Удивительно, но даже если Google Go скомпилирован с собственным кодом и рекламирует реализацию своих подпрограмм, Python по-прежнему побеждает.

Stackless будет полезен для реализации алгоритма отображения / уменьшения, где у вас может быть очень большое количество редукторов в зависимости от ваших входных данных.

12 голосов
/ 08 февраля 2010

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

Я думаю, что основная область, в которой они превосходят, - это когда у вас в программе выполняется много параллельных задач. Примерами могут быть игровые объекты, которые запускают сценарий зацикливания для своего ИИ, или веб-сервер, который обслуживает многих клиентов страницами, которые медленно создаются.

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

8 голосов
/ 12 февраля 2010

Тирлер уже упоминал, что в Eve Online использовался стек без стеков. Имейте в виду, что:

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

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

(получил эту цитату от здесь )

На PyCon 2009 был дан очень интересный доклад , описывающий, почему и как Stackless используется в CCP Games.

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

6 голосов
/ 17 февраля 2010

Хотя я сам не использовал Stackless, я использовал Greenlet для реализации высококонкурентных сетевых приложений. Linden Lab предлагает несколько вариантов использования: высокопроизводительные интеллектуальные прокси-серверы, быстрая система для распределения команд по огромному количеству машин и приложение, которое выполняет тонну записи и чтения базы данных (в соотношении около 1 : 2, что очень тяжело при записи, поэтому он тратит большую часть своего времени на ожидание возврата базы данных), и вещь типа веб-сканера для внутренних веб-данных. По сути, любое приложение, которое ожидает выполнения большого количества операций сетевого ввода-вывода, получит выгоду от возможности создавать баджиллионные легкие потоки. 10000 подключенных клиентов не кажутся мне огромной проблемой.

Stackless или Greenlet на самом деле не являются полным решением. Они очень низкоуровневые, и вам придётся приложить немало усилий, чтобы создать приложение, которое использует их в полной мере. Я знаю это, потому что я поддерживаю библиотеку, которая обеспечивает сетевой и диспетчерский уровень поверх Greenlet, особенно потому, что писать приложения намного проще с ним. Есть куча из них сейчас; Я поддерживаю Eventlet, но есть и Concurrence, Chiral, и, возможно, еще несколько, о которых я не знаю.

Если приложение, которое вы хотите написать, похоже на то, о чем я писал, рассмотрите одну из этих библиотек. Выбор Stackless vs Greenlet несколько менее важен, чем выбор библиотеки, которая лучше всего соответствует потребностям того, что вы хотите сделать.

6 голосов
/ 08 февраля 2010

EVEOnline в значительной степени запрограммирован в Stackless Python. У них есть несколько блогов разработчиков по его использованию. Кажется, это очень полезно для высокопроизводительных вычислений.

5 голосов
/ 16 февраля 2010

Основная польза для зеленых потоков, как я понимаю, состоит в том, чтобы реализовать систему, в которой у вас есть большое количество объектов, которые выполняют операции с большой задержкой. Конкретным примером будет связь с другими машинами:

def Run():
    # Do stuff
    request_information() # This call might block
    # Proceed doing more stuff

Потоки позволяют естественным образом писать приведенный выше код, но если количество объектов достаточно велико, потоки просто не могут работать адекватно. Но вы можете использовать зеленые нити даже в очень больших количествах. request_information() выше может переключиться на некоторый планировщик, где другая работа ожидает и вернуться позже. Вы получаете все преимущества возможности вызывать «блокирующие» функции , как если бы они немедленно возвращали без использования потоков.

Это, очевидно, очень полезно для любого вида распределенных вычислений, если вы хотите написать код простым способом.

Для нескольких ядер также интересно уменьшить количество ожидающих блокировок:

def Run():
    # Do some calculations
    green_lock(the_foo)
    # Do some more calculations

Функция green_lock в основном пытается получить блокировку и просто переключиться на главный планировщик, если она выйдет из строя из-за других ядер, использующих объект.

Опять же, зеленые потоки используются для уменьшения блокировок, позволяя писать код естественным образом и при этом работать хорошо.

...