Найти - Пользователи
Полная версия: Повышение производительности кода на питоне
Начало » Python для экспертов » Повышение производительности кода на питоне
1 2 3
izekia
Собственно здесь хотелось бы обсудить неожиданные результаты замеров, или просто поделиться опытом.
У меня следующий код:
from datetime import datetime
import psyco
psyco.full()

n = 1000000

def f1():
return [x+2 for x in range(n)]

def f2():
result = []
for x in range(n):
result.append(x+2)
return result

def f3():
result = []
for x in range(n):
result += [x+2]
return result

t = datetime.now()
f1()
print datetime.now() - t

t = datetime.now()
f2()
print datetime.now() - t

t = datetime.now()
f3()
print datetime.now() - t
выдал следующие результаты:
0:00:00.141000
0:00:00.094000
0:00:00.375000

Я вообще всегда считал, что метод используемый в f1 быстрее
izekia
а вот результаты без использования psyco
0:00:00.219000
0:00:00.313000
0:00:00.563000

PS: в данном тесте я заменил range на xrange
izekia
собственно добавил четвертую функцию такого вида:
def f4():
result = [0]*n
for x in xrange(n):
result[x] = x+2
return result
результаты с psyco:
0:00:00.125000
0:00:00.094000
0:00:00.375000
0:00:00.047000

и без него:
0:00:00.235000
0:00:00.312000
0:00:00.594000
0:00:00.172000

результаты более точных замеров:
psy&gc gc psyco clean
f1 0.11433 0.16656 0.10566 0.17885 sec/repeat in 10 repeats
f2 0.09519 0.30929 0.10910 0.30642 sec/repeat in 10 repeats
f3 0.38955 0.56423 0.38655 0.56900 sec/repeat in 10 repeats
f4 0.04510 0.17216 0.04500 0.17194 sec/repeat in 10 repeats
izekia
далее меня всегда интересовала производительность функции max
сначала я протестил следующий код:
from datetime import datetime
import psyco
psyco.full()

n = 10000000

def f1(l):
result = None
for x in l:
result = x if x > result else result
return result

def f2(l):
result = None
for x in l:
result = x > result and x or result
return result

def formList():
result = [0]*n
for x in xrange(n):
result[x] = x+2
return result

l = formList()
t = datetime.now()
max(l)
print datetime.now() - t

t = datetime.now()
f1(l)
print datetime.now() - t

t = datetime.now()
f2(l)
print datetime.now() - t
результат:
0:00:00.656000
0:00:00.141000
0:00:00.140000

небольшое отличие во второй и третьей строчках варьируется так же как и знак, то есть они идентичны, если не считать возможности попасть на нулевое значение x

без psyco результат получился более предсказуемым:
0:00:00.641000
0:00:01
0:00:01.109000

причем в последних двух строчках наблюдалось стабильное отличие на одну десятую

корректные результаты:
psy&gc gc psyco clean
fmax 0.53332 0.52626 0.53145 0.53093 sec/repeat in 10 repeats
f1 0.14818 0.96928 0.15452 0.97569 sec/repeat in 10 repeats
f2 0.14416 1.05048 0.13946 1.05867 sec/repeat in 10 repeats
izekia
далее упростим
следующая функция vs sum на миллионе значений:
def f1(l):
result = 0
for x in l:
result += x
return result
с psyco:
0:00:00.157000 sum
0:00:00.125000 f1

и без соответственно:
0:00:00.156000
0:00:00.219000

со встроенными функциями и psyco думаю тут все понятно

корректные результаты:
psy&gc gc psyco clean
sum 0.16274 0.15875 0.16075 0.15821 sec/repeat in 10 repeats
f1 0.11790 0.20511 0.11828 0.20757 sec/repeat in 10 repeats
izekia
кстати, заметил интересную вещь, касающуюся реализации max
почему-то max на убывающей последовательности из десяти миллионов значений стабильно был быстрее max на возрастающей примерно на 20%

результаты корректной проверки:
straight 0.53332 0.52626 0.53145 0.53093 sec/repeat in 10 repeats
reversed 0.51684 0.51587 0.51563 0.51735 sec/repeat in 10 repeats

решайте сами :)
izekia
Далее производительность filter
n = 1000000
m = 100

def fc(x):
return x > m

def f1(l):
return filter(fc, l)

def f2(l):
return filter(lambda x: x > m, l)

def f3(l):
result = []
for x in l:
if x > m:
result.append(x)
return result

def f4(l):
result = [0] * len(l)
i = 0
for x in l:
if x > m:
result[i] = x
i += 1
return result[:i]

def f4_1(l):
result = [0] * len(l)
i = 0
for j in xrange(len(l)):
if l[j] > m:
result[i] = l[j]
i += 1
return result[:i]

def f5(l):
result = [0] * len(l)
for i in xrange(len(l)):
if l[i] > m:
result[i] = l[i]
return filter(None, result)

def f6(l):
for i in reversed(xrange(len(l))):
if l[i] > m:
del l[i]
return l
с psyco:
0:00:00.687000 f1
0:00:00.641000 f2
0:00:00.109000 f3
0:00:00.078000 f4
0:00:00.078000 f4_1
0:00:00.094000 f5
0:00:00.094000 f6

без:
0:00:00.234000 f1
0:00:00.234000 f2
0:00:00.328000 f3
0:00:00.297000 f4
0:00:00.407000 f4_1
0:00:00.359000 f5
0:00:00.266000 f6

как и обещали на в документации, psyco замедляет filter

корректный результат:
psy&gc gc psyco clean
f1 0.24378 0.23986 0.24706 0.24388 sec/repeat in 10 repeats
f2 0.25300 0.23940 0.24666 0.24256 sec/repeat in 10 repeats
f3 0.10432 0.31685 0.09148 0.31327 sec/repeat in 10 repeats
f4 0.07580 0.30256 0.07696 0.31283 sec/repeat in 10 repeats
f4_1 0.08726 0.41106 0.08710 0.42220 sec/repeat in 10 repeats
f5 0.09956 0.38880 0.09490 0.37730 sec/repeat in 10 repeats
f6 0.12091 0.26931 0.11862 0.26855 sec/repeat in 10 repeats

поправил код f6:
def f6():
result = l[:]
for i in reversed(xrange(len(result))):
if result[i] > m:
del result[i]
return result
izekia
те же самые замеры соответственно, с m = 999900:
0:00:00.625000 f1
0:00:00.641000 f2
0:00:00.015000 f3
0:00:00.031000 f4
0:00:00.032000 f4_1
0:00:00.062000 f5
0:00:00.031000 f6

и
0:00:00.219000 f1
0:00:00.235000 f2
0:00:00.093000 f3
0:00:00.110000 f4
0:00:00.156000 f4_1
0:00:00.172000 f5
0:00:00.109000 f6

примерно можно представить какой алгоритм использует filter

корректные результаты:
psy&gc gc psyco clean
f1 0.23873 0.23442 0.22950 0.23179 sec/repeat in 10 repeats
f2 0.22903 0.22862 0.23583 0.22768 sec/repeat in 10 repeats
f3 0.01497 0.09107 0.01454 0.09062 sec/repeat in 10 repeats
f4 0.02838 0.10480 0.02876 0.10493 sec/repeat in 10 repeats
f4_1 0.03013 0.18873 0.03004 0.17896 sec/repeat in 10 repeats
f5 0.06586 0.21534 0.06629 0.21646 sec/repeat in 10 repeats
f6 0.06526 0.15384 0.06502 0.15343 sec/repeat in 10 repeats

результаты использования filter с psyco оказались несколько другие, так как в модуле был выключен psyco и он пытался обработать функции используемые в фильтре. Но думаю и с таким результатом целесообразность использования filter более чем очевидна
evgenyl
Афтар жёш давай ещё !!! :)
izekia
evgenyl
а что жжешь?
интересные, кстати, вещи, результатов многих замеров банально не ожидал
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB