Форум сайта python.su
0
Доброго времени суток всем форумчанам.
Пытаюсь освоить выгоду от исползования multi-core CPU + python.
Сразу скажу, про GIL читал вскользь.
Сначала опробывал синтаксис исползуя простенький примерчик, где в отделных процессах запускалась функция совершающая много несвязанных арифметических действий.
from multiprocessing import Process, Pool
import os, time
def f(arg):
mas = range(1, 10000)
p = 1
for i in mas:
p*=i*i*i*i
print 'parent process:', os.getppid(), 'process id:', os.getpid()
print "calculation", arg, "DONE"
if __name__ == '__main__':
t = time.time()
case = 2
if case == 0:
print 'POOL, 4x parallel calculation'
pool = Pool(processes = 4) # start 4 worker processes
pool.map(f, [1,2,3,4])
if case == 1:
print '4x parallel calculation'
p1 = Process(target=f, args=(1,))
p1.start()
p2 = Process(target=f, args=(2,))
p2.start()
p3 = Process(target=f, args=(3,))
p3.start()
p4 = Process(target=f, args=(4,))
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
if case == 2:
print 'serial calculation'
f(1)
f(2)
f(3)
f(4)
print "Time taken:", time.time() - t
4x parallel calculation
parent process: 24640 process id: 24643
calculation 3 DONE
parent process: 24640 process id: 24642
calculation 2 DONE
parent process: 24640 process id: 24641
calculation 1 DONE
parent process: 24640 process id: 24644
calculation 4 DONE
Time taken: 17.3200678825
serial calculation
parent process: 24649 process id: 24651
calculation 1 DONE
parent process: 24649 process id: 24651
calculation 2 DONE
parent process: 24649 process id: 24651
calculation 3 DONE
parent process: 24649 process id: 24651
calculation 4 DONE
Time taken: 27.8628590107
from multiprocessing import Process, Queue
import os, time
from random import randint
def f1(list1, list2):
for l1 in list1:
for l2 in list2:
if l1.xy == l2.xy:
list1.remove(l1)
list2.remove(l2)
break
#return list1, list2
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 ; x*x*x*x*x*x*x # some load
if __name__ == '__main__':
case = 0
npc_list = []
bullets_list = []
npc_list2 = []
bullets_list2 = []
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)
npc = ob((randint(1,100), randint(1,100)))
npc_list2.append(npc)
bullet = ob((randint(1,100), randint(1,100)))
bullets_list2.append(bullet)
i += 1
while True:
t = time.time()
if case == 0:
print "PARALLEL calc. using SAME objects"
p1 = Process(target=f1, args=(npc_list, bullets_list))
p1.start()
p2 = Process(target=f2, args=(npc_list, bullets_list))
p2.start()
p1.join()
p2.join()
if case == 1:
print "PARALLEL calc. using DIFFERENT objects"
p1 = Process(target=f1, args=(npc_list, bullets_list))
p1.start()
p2 = Process(target=f2, args=(npc_list2, bullets_list2))
p2.start()
p1.join()
p2.join()
if case == 2:
print "SERIAL calc."
f1(npc_list, bullets_list)
f2(npc_list, bullets_list)
print "Time taken:", time.time() - t
PARALLEL calc. using SAME objects
Time taken: 1.75695300102
Time taken: 1.71754407883
Time taken: 1.72614192963
PARALLEL calc. using DIFFERENT objects
Time taken: 1.70828604698
Time taken: 1.69986701012
Time taken: 1.74617981911
SERIAL calc.
Time taken: 1.66356611252
Time taken: 0.824527978897
Time taken: 0.73535490036
Time taken: 0.86488699913
Time taken: 0.710259914398
Отредактировано (Дек. 12, 2010 15:52:29)
Офлайн
13
По-моему у вас там что-то с данными. Они по виду меняются в тесте.
Я попробовал изолировать данные и у меня результаты вполне вменяемые.
Вот слегка модифицированый ваш код: http://pastebin.com/R4mjTzNg
Вот результат:
$ python proc1.py
PARALLEL calc. using DIFFERENT objects
f1: 1000 1000
f1: 1000 1000
f1: 1000 1000
f2: 1000 1000
f2: 1000 1000
f2: 1000 1000
f2: 1000 1000
f1: 1000 1000
Time taken: 1.4449698925
SERIAL calc.
f1: 1000 1000
f1: 1000 1000
f1: 1000 1000
f1: 1000 1000
f2: 1000 1000
f2: 1000 1000
f2: 1000 1000
f2: 1000 1000
Time taken: 2.7552011013
Офлайн
2
amdlintuxosПри использовании процессов GIL не играет никакой роли. Это вообще из другой оперы.
Тут я стал думать о GIL, и как я его понял.
Офлайн
0
Александр КошелевЯ читал много постов и очень много жалоб было на GIL, я уже засомневался что питон(стандартный) позволит исползовать эффективно MultiCore CPU, я ошибся и подвергся паранои. спасибо за разяснение, значит не всё так плохо.
При использовании процессов GIL не играет никакой роли. Это вообще из другой оперы.
Edверно, но их изменение не так значительно чтоб сказыватся на тесте, в любом случае я исключил это влияние.
По-моему у вас там что-то с данными. Они по виду меняются в тесте
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:
t = time.time()
for case in [0,1]:
if case == 0:
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()
p1.join()
p2.join()
if case == 1:
print "SERIAL calc."
f1(npc_list, bullets_list)
f2(npc_list, bullets_list)
print "Time taken:", time.time() - t
PARALLEL calc.
Time taken: 0.963114023209
SERIAL calc.
Time taken: 2.58085608482
PARALLEL calc.
Time taken: 0.948005914688
SERIAL calc.
Time taken: 2.55663514137
PARALLEL calc.
Time taken: 0.969657897949
SERIAL calc.
Time taken: 2.60941004753
PARALLEL calc.
Time taken: 0.962624788284
SERIAL calc.
Time taken: 2.59019184113
PARALLEL calc.
Time taken: 0.946449995041
SERIAL calc.
Time taken: 2.56901907921
PARALLEL calc.
Time taken: 0.953253984451
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
case = 1
while True:
t = time.time()
if case == 0:
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()
p1.join()
p2.join()
if case == 1:
print "SERIAL calc."
f1(npc_list, bullets_list)
f2(npc_list, bullets_list)
print "Time taken:", time.time() - t
SERIAL calc.
Time taken: 1.61172699928
SERIAL calc.
Time taken: 1.60983991623
SERIAL calc.
Time taken: 1.60948204994
SERIAL calc.
Time taken: 1.61442399025
SERIAL calc.
Отредактировано (Дек. 13, 2010 20:15:05)
Офлайн
13
amdlintuxosУ вас там баг в подсчете времени в коде 1. Внесите t = time.time() вовнутрь цикла.
Как видите различия в коде 1 и коде 2 незначительны.
почему же время исполнения последователных вычеслений кода 1 (2.5сек), а кода 2 (1.6сек)?
Офлайн
0
Edпозорный мой недочёт. спасибо большое за помощь. теперь всё встало на свои места.
У вас там баг в подсчете времени в коде 1. Внесите t = time.time() вовнутрь цикла.
Офлайн