Как стать автором
Обновить

Комментарии 18

Собственно вопрос разработчику ядра:
Когда допилите GIL до изоляции на уровне суб-интерпретаторов?

Насчёт GIL — это просто bool, который устанавливается используя блокировку и не мешает многопоточно выполнять C++ коду в отдельном потоке.
Полагаю, к версии 4.0
bugs.python.org/issue15751 если будет сделан поможет написать работу с субинтерпретаторами правильно (PyGILState_Ensure умеет жить только с главным интерпретатором если что).

Основная беда следующая: субинтерпретаторы разделяют слишком много данных. Если питоновский код еще можно как-то развести по углам, то с C Extensions полная беда.

По сложившейся практике данные модуля все хранят как static variables. Существует PEP 3121 для module state, но пока его никто не реализовывает (благо что необязательный).
Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS позволяют параллельное выполнение даже в питоновских потоках.

И, естественно, ничто не мешает создавать отдельные потоки, о которых Питон ничего не знает.

Только Python API без GIL вызывать нельзя. Хоть и очень хочется.

К слову, PyGILState_Ensure/PyGILState_Release — довольно дорогая операция.
Лучше делать её один раз на поток, используя PyEval_SaveThread/PyEval_RestoreThread для временного отпускания GIL.
Можно ли объявить эти static variables как threadlocal? Будет ли в этом случае работать описанная выше схема?
Субинтерпретаторы не обязаны работать в разных потоках. Т.е. должна поддерживаться в том числе и схема, при которой несколько субинтерпретаторов разделяют один поток. threadlocal здесь не помогут.
Я так понимаю, что в этом случае с собой надо всегда носить контекст, а для этого нужно перелопатить кучу кода как CPython, так и его модулей.

PEP-3121, упомянутый Вами, это и предлагает.
Всё верно, нужно перелопатить много кода, причем основной объем в третьесторонних библиотеках. PEP 3121 не предлагает «контекст», он только дает место для хранения переменных модуля и всё.
На multiprocessing можно реализовать практически любые вещи, которые делаются, например, в java при помощи «нормальных» тредов. Может написать пару статтей, как обмениваться данными между питоническими процессами, делать их синхронными и асинхронными, делать процессы-слушатели и т.п.?
А разве есть какие-то хитрые питонические способы обмена данными между процессами, кроме как средствами ОС?
(а значит, со всяческими сериализациями)
Конечно есть. Например можно делать общее пространство имён между процессами:
import multiprocessing

def producer(ns, event):
    ns.value = 'This is the value'
    event.set()

def consumer(ns, event):
    try:
        value = ns.value
    except Exception, err:
        print 'Before event, consumer got:', str(err)
    event.wait()
    print 'After event, consumer got:', ns.value

if __name__ == '__main__':
    mgr = multiprocessing.Manager()
    namespace = mgr.Namespace()
    event = multiprocessing.Event()
    p = multiprocessing.Process(target=producer, args=(namespace, event))
    c = multiprocessing.Process(target=consumer, args=(namespace, event))
    
    c.start()
    p.start()
    
    c.join()
    p.join()
Тогда да, статьи были бы интересны.
Особенно с прикручиванием к twisted.
Если быть точным, namespace внутри использует pickle или xmlrpclib.
В multiprocessing очень много всего.

Мне, например, нравится работа через Pipe для передачи комплексных переменных между процессами.
а питоновые объекты так передавать можно?
Да
Фактически все нетривиальные (не int, float, str) типы используют сериализацию. Т.к. picke обычно замечательно работает для multiprocessing «из коробки» — никаких неудобств это не доставляет и происходит незаметно для программиста.
Подскажите, когда планировщик забирает у питоноского потока слайс через 5 миллисекунд — он это может сделать в любом месте? Например, если у меня есть франмент кода на питоне:

somelist.insert( 0, somelist.pop() )


Поток может быть остановлен после того как элемент изъят из конца списка но до того, как он добавлен в начало списка? Есть какие-то ограничения на то, когда поток можно останавливать — или в абсолютно любое время, так же как в операционных системах?
Переключение GIL может произойти перед выполнением любого байткода. Так что всё верно: ваш пример не атомарный.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации