Форум сайта python.su
Привет всем
Почитав книги и в интернете, если я правильно понял, то питоновский интерпретатор jpython поддерживает многопоточность исполнения кода питона, в отличие от cpython с его GIL'ом. Если запустить установленный по умолчанию интерпретатор, то выдаётся такое:
Python 3.1.2 (r312:79147, Apr 15 2010, 15:35:48)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
Отредактировано (Дек. 21, 2010 15:36:05)
Офлайн
CPython.
Дался вам этот GIL - плохому танцору ноги мешают.
Офлайн
Да, дался!
Мне нужно писать приложение, работающее и использующее многоядерность. По информации в интернете, советуют использовать многопроцессорность на основе модуля multiprocessing, чем многопоточность. Кто писал подобные приложения, дайте свою оценку и мнения по поводу написания этих приложений
Кстати, вы определили по надписи GCC?
Отредактировано (Дек. 21, 2010 16:58:07)
Офлайн
По номеру svn версии - я их наизусть помню. Кроме того, jython плотно застрял на 2.5
Многоядерность по факту не очень то и нужна. Не часто встречал программы, эффективно грузящие хотя бы одно ядро.
Но если очень хочется - то да, multiprocessing хорошо помогает. В умелых руках быстр и удобен.
Офлайн
Андрей Светловсам недавно задавался тем же вопросом.
советуют использовать многопроцессорность на основе модуля multiprocessing
from multiprocessing import Process, Queue
import os, time
from random import randint
def f1(list1, list2):
for l1 in list1:
for l2 in list2:
(x,y) = l2.xy # some load
x*x*x*x*x*x*x # some load
def f2(list1, list2):
for l1 in list1:
l1.render()
for l2 in list2:
l2.render()
class ob():
def __init__(self, (x,y)):
self.xy = (x,y)
def render(self):
(x, y) = self.xy # some load
x*x*x*x*x*x*x # some load
if __name__ == '__main__':
npc_list = []
bullets_list = []
i = 0
while i < 1000:
npc = ob((randint(1,100), randint(1,100)))
npc_list.append(npc)
bullet = ob((randint(1,100), randint(1,100)))
bullets_list.append(bullet)
i += 1
while True:
for case in [0,1]:
if case == 0:
t = time.time()
print "PARALLEL calc."
p1 = Process(target=f1, args=(npc_list, bullets_list))
p1.start()
p2 = Process(target=f2, args=(npc_list, bullets_list))
p2.start()
p3 = Process(target=f1, args=(npc_list, bullets_list))
p3.start()
p4 = Process(target=f2, args=(npc_list, bullets_list))
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
print "Time taken:", time.time() - t
if case == 1:
t = time.time()
print "SERIAL calc."
f1(npc_list, bullets_list)
f2(npc_list, bullets_list)
f1(npc_list, bullets_list)
f2(npc_list, bullets_list)
print "Time taken:", time.time() - t
PARALLEL calc.
Time taken: 0.973960161209
SERIAL calc.
Time taken: 3.24503898621
Отредактировано (Дек. 21, 2010 18:53:28)
Офлайн
Поддержу: “плохому танцору ноги мешают”.
Многопоточное исполнение может понадобиться в двух случаях:
1 Вам удобнее думать что в программе есть много кусков ()
2 вам надо чтобы быстро что-то посчиталось
В первом случае достаточно обычных потоков. (Потоки все сидят и чего-то ждут - коннектов к базе, слушают сокеты, ждут когда пользователь ткнет в кнопку и т.п.)
Во втором случае нужен multiprocessing если надо считать именно интерпретатором.
У multiprocessing есть недостаток - большое время старта процесса - десятки миллисекунд.
Но если вы боретесь за производительность то первое что вы сделаете - откомпилируете критические куски кода и распараллелите все что можно на нижнем уровне, поэтому какой питон и какой модуль использовать - безразлично. Для расчетов можно использовать и готовые распараллеленые библиотеки предметной области - их полно для линейной алгебры. Есть еще конечно http://www.parallelpython.com/ или pyMPI. Но большего эффекта можно добиться только ручками на нижнем уровне.
Могу даже примерно описать что произойдет: Получите от 4 ядер ускорение раза в 2-3 потом подцепите GUDA это приведет к тому, что побежите менять кулер на процессоре и видюшке и покупать новый блок питания. После этого получите 10-30 кратное ускорение :), если будет мало начнете строить grid или умыкнете где-нибудь суперкомпьютер.
Мой опыт показывает - построить счетную систему полностью грузящую 4-8 ядер на cpython - легко.
Отредактировано (Дек. 21, 2010 22:47:24)
Офлайн
doza_and, на линуксе multiprocessing.Process стартует 1 мс. Что, конечно, в 6-7 раз хуже чем threading.Thread - но вполне сопоставимо.
А в остальном - все верно.
Офлайн
На windows XP SP3 под python 2.6 первый старт multiprocessing.Process был порядка 50 ms (прмерно) последующие 20-30 ms. Наверное это зависит от конфигурации системы, но такие времена конечно могут потребовать применения своеобразной оптимизации алгоритма :(. За информацию про linux Андрей большое спасибо, буду использовать. Там померить просто руки не дошли.
Еще наверное стоит отметить для wertklop что время создания тредов в threading.Thread можно существенно амортизировать используя thread pool который позволит повторно использовать созданные однажды треды.
Отредактировано (Дек. 22, 2010 20:40:09)
Офлайн