Pull to refresh

Comments 15

Если я не ошибаюсь у multiprocessing есть ограничение по организации файлов проекта. Что-то связанное с запускаемым файлом и __main__ или я ошибаюсь?
Требуется, что бы можно было импортировать пакет __main__ без side-effects.
Да, в Windows необходимо писать:

from multiprocessing import Process

def foo():
    print 'hello'

if __name__ ==  '__main__':
    p = Process(target=foo)
    p.start()

В Linux это не обязательно. Но так как писать межплатформенный код это правильно, то в своих скриптах я точку входа стараюсь оборачивать в if __name__ == '__main__'.
Я пот винду вообще не пишу, но оборачивать иполняемую часть модуля в «if __name__ == '__main__'» это хороший тон.
Под windows нет fork(), соотвественно запускается вторая инстанция самого python, которая выполняется до места «разветвления». И тут возникает необходимость в некоторых архитектурных решениях (если код сложнее 1-2 небольших файлов).
А как shared array внутри реализуется?
Я могу ошибаться. Но в Linux это вроде бы mmap через /dev/shm.
Я тут, знакомясь с Хоаровскими CSP нашел на занятную их реализацию на питоне — в частности, она позволяет писать один и тот же код с CSP-примитивами (параллельная композиция, всякие guarded alternative и т.д.) и исполнять его двумя с способами — поверх легковесных сопрограмм greenlet в одном процессе, что дает миллионы «нитей» на одной машине, либо с помощью полноценных процессов (в т.ч. уже связанных по TCP/IP). В продакшене не замечена, но на практикуме по параллельному программриованию, как я понял, студентами мучается уже не первый год.

Кто-нибудь сталкивался?
Из Википедии:
«GIL освобождается при исполнении кода большинства расширений, например, NumPy/SciPy, позволяя на время расчётов исполняться другому Python потоку.»
Спасибо за очень правильный вопрос! При ответе на него я буду пользоваться официальной информацией с сайта разработчиков SciPy о возможности параллелизации NumPy/SciPy. Там внизу есть интересная табличка сравнения времени выполнения кода с использованием нитей и потоков.

Прежде всего да, вы абсолютно правы. GIL действительно освобождается при выполнении кода NumPy. Но! Есть два «но». Прежде всего оверхед при использовании нитей все-таки больше, чем при использовании процессов. Но это еще как-то можно было бы пережить.

Второе «но» важнее. В случае если в нитке используются циклы, то GIL не освобождается и параллельное выполнение становится чуть ли не два раза дольше последовательного. А в реальных программах не всегда удается полностью векторизовать код. Часто остаются какие-либо мелкие циклы, векторизовать которые не слишком удобно. И в случае нитей параллельное программирование превращается в крайне неудобный процесс гадания, отпустится ли GIL или нет. И какой цикл на это влияет. При этом, что самое неприятное, параллельный код может быть в несколько раз медленне последовательного.

В случае процессов мы избавлены от этих проблем и невекторизованный код проблемы не представляет. А точки зрения архитектуры мы все-равно работаем в парадигме нитей и общей памяти. Поэтому решение проблемы GIL при помощи процессов и shared memory мне кажется наиболее практичным.
На Python с использование matplotlib. Стрелки уже сверху я нарисовал в Gimp. Полный код построения графиков приведен в конце поста в полном коде скрипта. Метод showTimePlot().
Может быть кому-то будет интересно, но я в своей старой статье тоже рассматривал вопрос скорости выполнения кода через распараллеливание на основе OpenMP
Sign up to leave a comment.

Articles