Post on 29-Nov-2014
description
Быстрые конструкции в python
Циклы
val = 0i = 0while i < 10000: val += i i += 1
from functools import reducereduce(lambda res, x: res+x, range(10000))
val = 0for i in range(10000): val += i
val = 0for i in xrange(10000): val += i
0.415 мс.
744 мс.
0.322 мс.
0.883 мс.
Условия
10 < 10.0
10.0 < 10.0
10 < 10
0.0 + 10
float(10)
Str(10)
"{0}".format(10)
48.5 нс
38.4 нс
26.8 нс
15.8 нс
100 нс
137 нс
116 нс
Список / Словарьa = [i for i in range(100000)]
a = [0]*100000for i in a: a[i] = i
a = []for i in range(100000): a = a + [i]
a = []for i in range(100000): a += [i]
a = []for i in range(100000): a.append(i)
a = []append = a.appendfor i in range(100000): append(i)
8.9 мс
10.2 мс
37000 мс (37 с.)
14.2 мс
8.8 мс
6.03 мс
Список / Словарьwords = ['asjasjd', 'akaksd', 'ajskskd', 'kasald']
a = {}for word in words: if word not in a: a[word] = 0 a[word] += 1
a = {}for word in words: try: a[word] += 1 except KeyError: a[word] = 1
a = {}get = a.getfor word in words: a[word] = get(word, 0) + 1
852 нс
1600 нс
681 нс
Арифметические операции
pow(3, 30)
3 ** 30
math.sqrt(144)
144 ** .5
k = 1000
k >> 1
k / 2
k << 1
k * 2
189 нс
16.2 нс
68.3 нс
15.8 нс
39 нс
38 нс
50.3 нс
52.3 нс
65.6 нс
49.9 нс
68.8 нс
45.1 нс
Python 2 Python 3
Строкиstr1 = 'val1'str2 = 'val2'str3 = 'val3'
'str1: {} str2: {} str3: {}'.format(str1, str2, str3)
"".join(['str1: ', str1, 'str2: ', str2, 'str3: ', str3])
'str1: ' + str1 + ' str2: ' + str2 + ' str3: ' + str3
'str1: %s str2: %s str3: %s' % (str1, str2, str3)
'str1: {0} str2: {1} str3: {2}'.format(str1, str2, str3)
a = ['str1: ', str1, 'str2: ', str2, 'str3: ', str3] "".join(a)
s = 'trashtrashtrashtrashabrakadabratrash'
if s.find('abra') != -1 : pass
if 'abra' in s : pass
299 нс
284 нс
243 нс
235 нс
192 нс
152 нс
162 нс
44.3 нс
Python медленный ?
Пример задачи
Задан массив чисел. И поступила n запросов найти сумму от l до r.
Очевидный вариант:
s = 0 for i in range(l, r+1): s += a[i]
Продвинутый вариант:
sum(a[l:r+1])
Тест: 10000 элементов, n = 10
0.49 сек.
0.224 сек.
Написать быструю структуру данных (Дерево отрезков):
class Tree(): def __init__(self, a): self.a = a self.t = [0] * len(a)*4 self.build_tree(1, 0, len(self.a)-1)
def build_tree(self, v, l, r): if l == r: self.t[v] = self.a[l] return self.t[v] mid = (l+r) // 2 self.t[v] = self.build_tree(v*2, l, mid) + self.build_tree(v*2+1, mid+1, r) return self.t[v]
def slice(self, v, l, r, tl, tr): if l == tl and r == tr: return self.t[v]
mid = (l+r) // 2 if tl >= l and tr <= mid: return self.slice(v*2, l, mid, tl, tr) if tl >= mid+1 and tr <= r: return self.slice(v*2+1, mid+1, r, tl, tr)
return self.slice(v*2, l, mid, tl, mid) + self.slice(v*2+1, mid+1, r, mid+1, tr)
0.1 сек.
Пример задачи
Посчитать N-ое число Фибоначчи. (1, 1, 2, 3, 5, 8, 13 …. )
def fib(n): a = 0 b = 1 for i in xrange(n): a, b = b, a+b return a
def fib2(n): matrix = [[1, 1], [1, 0]] return bin_pow(matrix, n+1)[1][1]
370 мс.
43.4 мс.
При n = 3000 При n = 10^7
25 мин.
89 мс.
cpmoptimize
from cpmoptimize import cpmoptimize
@cpmoptimize()def fib(n): a = 0 b = 1 for i in xrange(n): a, b = b, a+b return a
При n = 3000 При n = 10^7
368 мс. 13 сeк.
cpmoptimize
cpmoptimize.xrange(start, stop[, step])
cpmoptimize.cpmoptimize(strict=False, iters_limit=5000, types=(int, long), opt_min_rows=True, opt_clear_stack=True)
Плюсы:
- ускоряет работу программы- поддерживает большие типы данных- легкий в использовании- заботится о памяти
Минусы:
- оптимизирует только если все константы и переменные, используемые в нём, имеют допустимый тип- Тело цикла должно состоять только из инструкций присваивания, унарных и бинарных операций- Не может содержать условий, вызовов других функций, операторов return и yield
Другие методы ускорения
1) PyPy — альтернативный интерпретатор Python с поддержкой JIT-компиляции
2) Pyston — новый альтернативный интерпретатор Python, транслирующий код в промежуточное представление LLVM
3) Nuitka — компилятор Python. Умеет создавать exe файлы
4) astoptimizer — библиотека, применяющая известные методы оптимизации перед компиляцией в байт-код путём анализа и изменения абстрактного синтаксического дерева.
5) foldy.py — библиотека, анализирующая байт-код и выполняющая сворачивание констант а также удаление неиспользуемых функций
6) Numba — библиотека, ускоряющая программы, содержащие математические вычисления и операции с массивами. Оптимизация происходит за счёт JIT-компиляции
7) Cython — оптимизирующий компилятор надмножества языка Python, позволяющий использовать в программе статическую типизацию и тесно взаимодействовать с кодом на C и C++.
Вывод
1) Если что-то можно заменить на встроенные функции – надо менять, т.к. VM довольно медленная.
2) Будьте внимательны к типам, так как из-за них можно потерять скорость в 2-4 раза
3) Меньше глобальных переменных
4) Придумывайте алгоритмы
5) Если не смогли придумать пользуйтесь оптимизациями