Комментарии 18
Собственно вопрос разработчику ядра:
Когда допилите GIL до изоляции на уровне суб-интерпретаторов?
Насчёт GIL — это просто bool, который устанавливается используя блокировку и не мешает многопоточно выполнять C++ коду в отдельном потоке.
Когда допилите GIL до изоляции на уровне суб-интерпретаторов?
Насчёт GIL — это просто bool, который устанавливается используя блокировку и не мешает многопоточно выполнять C++ коду в отдельном потоке.
Полагаю, к версии 4.0
bugs.python.org/issue15751 если будет сделан поможет написать работу с субинтерпретаторами правильно (PyGILState_Ensure умеет жить только с главным интерпретатором если что).
Основная беда следующая: субинтерпретаторы разделяют слишком много данных. Если питоновский код еще можно как-то развести по углам, то с C Extensions полная беда.
По сложившейся практике данные модуля все хранят как static variables. Существует PEP 3121 для module state, но пока его никто не реализовывает (благо что необязательный).
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.
И, естественно, ничто не мешает создавать отдельные потоки, о которых Питон ничего не знает.
Только 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()
В multiprocessing очень много всего.
Мне, например, нравится работа через Pipe для передачи комплексных переменных между процессами.
Мне, например, нравится работа через Pipe для передачи комплексных переменных между процессами.
Фактически все нетривиальные (не int, float, str) типы используют сериализацию. Т.к. picke обычно замечательно работает для multiprocessing «из коробки» — никаких неудобств это не доставляет и происходит незаметно для программиста.
Подскажите, когда планировщик забирает у питоноского потока слайс через 5 миллисекунд — он это может сделать в любом месте? Например, если у меня есть франмент кода на питоне:
Поток может быть остановлен после того как элемент изъят из конца списка но до того, как он добавлен в начало списка? Есть какие-то ограничения на то, когда поток можно останавливать — или в абсолютно любое время, так же как в операционных системах?
somelist.insert( 0, somelist.pop() )
Поток может быть остановлен после того как элемент изъят из конца списка но до того, как он добавлен в начало списка? Есть какие-то ограничения на то, когда поток можно останавливать — или в абсолютно любое время, так же как в операционных системах?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Еще раз о многопоточности и Python