На Python с использование matplotlib. Стрелки уже сверху я нарисовал в Gimp. Полный код построения графиков приведен в конце поста в полном коде скрипта. Метод showTimePlot().
Спасибо за очень правильный вопрос! При ответе на него я буду пользоваться официальной информацией с сайта разработчиков SciPy о возможности параллелизации NumPy/SciPy. Там внизу есть интересная табличка сравнения времени выполнения кода с использованием нитей и потоков.
Прежде всего да, вы абсолютно правы. GIL действительно освобождается при выполнении кода NumPy. Но! Есть два «но». Прежде всего оверхед при использовании нитей все-таки больше, чем при использовании процессов. Но это еще как-то можно было бы пережить.
Второе «но» важнее. В случае если в нитке используются циклы, то GIL не освобождается и параллельное выполнение становится чуть ли не два раза дольше последовательного. А в реальных программах не всегда удается полностью векторизовать код. Часто остаются какие-либо мелкие циклы, векторизовать которые не слишком удобно. И в случае нитей параллельное программирование превращается в крайне неудобный процесс гадания, отпустится ли GIL или нет. И какой цикл на это влияет. При этом, что самое неприятное, параллельный код может быть в несколько раз медленне последовательного.
В случае процессов мы избавлены от этих проблем и невекторизованный код проблемы не представляет. А точки зрения архитектуры мы все-равно работаем в парадигме нитей и общей памяти. Поэтому решение проблемы GIL при помощи процессов и shared memory мне кажется наиболее практичным.
from multiprocessing import Process
def foo():
print 'hello'
if __name__ == '__main__':
p = Process(target=foo)
p.start()
В Linux это не обязательно. Но так как писать межплатформенный код это правильно, то в своих скриптах я точку входа стараюсь оборачивать в if __name__ == '__main__'.
Прежде всего да, вы абсолютно правы. GIL действительно освобождается при выполнении кода NumPy. Но! Есть два «но». Прежде всего оверхед при использовании нитей все-таки больше, чем при использовании процессов. Но это еще как-то можно было бы пережить.
Второе «но» важнее. В случае если в нитке используются циклы, то GIL не освобождается и параллельное выполнение становится чуть ли не два раза дольше последовательного. А в реальных программах не всегда удается полностью векторизовать код. Часто остаются какие-либо мелкие циклы, векторизовать которые не слишком удобно. И в случае нитей параллельное программирование превращается в крайне неудобный процесс гадания, отпустится ли GIL или нет. И какой цикл на это влияет. При этом, что самое неприятное, параллельный код может быть в несколько раз медленне последовательного.
В случае процессов мы избавлены от этих проблем и невекторизованный код проблемы не представляет. А точки зрения архитектуры мы все-равно работаем в парадигме нитей и общей памяти. Поэтому решение проблемы GIL при помощи процессов и shared memory мне кажется наиболее практичным.
docs.python.org/2/library/multiprocessing.html#multiprocessing-programming
В Linux это не обязательно. Но так как писать межплатформенный код это правильно, то в своих скриптах я точку входа стараюсь оборачивать в if __name__ == '__main__'.