Top Banner
Python и Cython Оптимизация и стыковка с C Александр Шигин, [email protected] Rambler, 2010
53

Python и Cython

May 28, 2015

Download

Technology

Удобное ускорения Python'а с помощью Cython.

Доклад для devconf-2010.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Python и Cython

Python и CythonОптимизация и стыковка с C

Александр Шигин, [email protected], 2010

Page 2: Python и Cython

Python — удобно

... но не быстро

Page 3: Python и Cython

Python — удобно... но не быстро

Page 4: Python и Cython

• динамический язык;• байт код без компиляции;• GC на счетчике ссылок;• Global Interpretor Lock;• если что-то работает медленнееpython’а, это не значит чтоpython быстрый.

Page 5: Python и Cython

• динамический язык;• байт код без компиляции;• GC на счетчике ссылок;• Global Interpretor Lock;• если что-то работает медленнееpython’а, это не значит чтоpython быстрый.

Page 6: Python и Cython

Еще про ref-counting

• процессы — плохая заменатредам;

• не работает Copy–on–Write;• мы не можем легкораспараллелить программу,когда у нас много данных.

Page 7: Python и Cython

...d = d i c t ( ( i , ’ the ␣ s t r i n g ␣wi th ␣%d ’ % i )

for i in x range (500∗1000))t ime . s l e e p (10)s y s . s t d e r r . w r i t e ( ’ about ␣ to ␣ f o r k . . . \ n ’ )os . f o r k ( )

for i , k in d . i t e r i t e m s ( ) :pass

t ime . s l e e p (10)

Page 8: Python и Cython

C — не так удобно

... но достаточнобыстро

Page 9: Python и Cython

C — не так удобно... но достаточно

быстро

Page 10: Python и Cython

C + Python = ???

медленнее Cа удобно?

Page 11: Python и Cython

C + Python =

???

медленнее C

а удобно?

Page 12: Python и Cython

C + Python =

???

медленнее Cа удобно?

Page 13: Python и Cython

Pythondef sum_th(lst):

result = 0for i in lst: #!

result += i.th #!!!111return result

Page 14: Python и Cython

Pure Clong sum_th(const struct with_th_t *all,

size_t size) {long result = 0;size_t i;for (i = 0; i < size; ++i) {

result += all[i].th;}return result;

}

Page 15: Python и Cython

Модуль на Cwhile ((item = PyIter_Next(iterator)) != NULL) {

PyObject *field = PyObject_GetAttr(item, interned_th);

if (field == NULL) {Py_DECREF(result);Py_DECREF(item);return NULL;

}PyObject *nw = PyNumber_Add( result, field);Py_DECREF(result);...

Page 16: Python и Cython

Python

def sum_th(lst):result = 0for i in lst: #!

result += i.th #!!!111return result

Page 17: Python и Cython

Осторожно,benchmark!

Page 18: Python и Cython

Итого

Python Pure C C moduleстрок 5 7 28

• На реальном коде разница будетменьше!

• Но разница будет.

Page 19: Python и Cython

???

Долго писать:• много кода;• сложность отладки.

Потеря скорости:• boxing/unboxing.

Page 20: Python и Cython

boxing/unboxing

PyInt_FromSize_t

PyInt_FromLong PyLong_FromSize_t

fill_free_list _PyLong_FromByteArray

_PyLong_New

Page 21: Python и Cython

boxing/unboxingPyInt_AsLong

PyInt_Check tp_as_number

PyInt_AS_LONG PyInt_Check

PyInt_AS_LONG PyLong_Check

PyLong_AsLong

Page 22: Python и Cython

Cython

• страшная смесь Python’а и C;• понимает подмножество Python;• генерирует C-код;• def/cdef/cpdef.• lxml, SciPy, ...

Page 23: Python и Cython

• читайте FAQ;• используйте cdef;• не *q = 0, а q[0] = 0;• не путайте float и double;• cdef для переменных, которыеучаствуют в циклах;

• cython -a.

Page 24: Python и Cython

shlex.split• Ускорим простую программув XX раз.

• За 15 минут.• Сейчас это займет куда меньшевремени.

Page 25: Python и Cython

Задача127.0.0.1 "it’s query" "client id" 12.0 ...

• str.split не сработает: некоторыеполя окружены кавычками.

• 25 миллионов строк в день.• 680 миллионов строк в месяц.

Page 26: Python и Cython

Что имеемsm = 0.0cnt = 0for line in sys.stdin:

split = shlex.split(line)try:

sm += float(split[12])cnt += 1

except ValueError:pass

Page 27: Python и Cython

Что имеемИспользуем стандартный shlex.split и файл в 900строк.

SUMMARYreal time: 0.870 [ 0.875 +-0.004] 0.878sys time: 0.004 [ 0.007 +-0.002] 0.008user time: 0.844 [ 0.860 +-0.014] 0.868

≈ 1 мс на строку.≈ 7 часов на дневной лог

Page 28: Python и Cython

Что имеем

Своя, очень простая реализация. Тот же файл.

SUMMARYreal time: 0.603 [ 0.614 +-0.009] 0.621sys time: 0.000 [ 0.001 +-0.002] 0.004user time: 0.596 [ 0.601 +-0.006] 0.608

≈ 0.7 мс на строку.≈ 5 часов на дневной лог

Page 29: Python и Cython

Что имеем

Та же реализация, но откомпилированная вcython. Тот же файл.

SUMMARYreal time: 0.650 [ 0.664 +-0.013] 0.675sys time: 0.000 [ 0.000 +-0.000] 0.000user time: 0.640 [ 0.655 +-0.014] 0.668

Page 30: Python и Cython

cython -a

Page 31: Python и Cython

Уберем Python API

Page 32: Python и Cython

Уберем Python API

Page 33: Python и Cython

Time table

время0.603 исходный код0.532 объявить типы0.151 cdef class0.029 char *

≈ 14 минут на дневной лог файл.

Page 34: Python и Cython

Cython vs ...

• boost::python;• SWIG;• expy;• ...

Page 35: Python и Cython

Проблема boxing/unboxing

1 Найдем функцию, что занимает>50% времени.

2 Перепишем её на C.3 ???

4 Нет профита.

Page 36: Python и Cython

Проблема boxing/unboxing

1 Найдем функцию, что занимает>50% времени.

2 Перепишем её на C.3 ???4 Нет профита.

Page 37: Python и Cython

Профилирование

Подход ускорения черезпрофилирование порочен:• не надо думать, что остальнаяпрограмма ускорится;

• что делать, если нет очевидногомедленного места?

Page 38: Python и Cython

Кроме этого

• на каждый вызов функции надопреобразовывать данные;

• в вырожденных случаях, этобудет дольше самой функции;

• мы вынуждены переписыватьвсе места, где мы вызываемнашу функцию.

Page 39: Python и Cython

Решение

• частичная оптимизация;• cpdef;• перетаскивание функционала вcython, а потом в C;

• это не панацея.

Page 40: Python и Cython

Сложные данные

Как работать с данными из C иPython.• proxy/wrapper;• копия.

Page 41: Python и Cython

Копирование vs proxy

proxy:• каждый раз преобразовывать;• но есть кеш объектов;• код на C работает быстро;• это тот код, который насинтересует.

Page 42: Python и Cython

Копирование vs proxy

Копирование:• идеально для неизменяемыхобъектов;

• но требует много памяти;• fork...

Page 43: Python и Cython

Еще раз про GIL

Page 44: Python и Cython

GIL — это непроблема

Page 45: Python и Cython

GIL

• он нужен, пока мы работаем сpython данными;

• в критичных местах, мы неработаем с python данными;

• мы можем его отпустить.

Page 46: Python и Cython

proxy: запрет создания изpython

cdef class _Q:def __cinit__(self, ....):

....

def __init__(self, ....):raise TypeError, ""

cpdef _Q Q(....):cdef _Q q = _Q.__new__(_Q)return q

Page 47: Python и Cython

Кеширование объектов

• попробуйте id;• попробуйте перенумеровать взависимости от частоты;

• убедитесь, что у васнеизменяемые типы;

• треды...

Page 48: Python и Cython

Кеширование проксиобъектов

Python container a[0] a[1] ... a[n]

C struct ... void *extra

container struct Python proxy

Page 49: Python и Cython

Кеширование проксиобъектов

Python container a[0] a[1] ... a[n]

C struct ... void *extra__getitem__

Python proxy container struct next Python proxy ...

Page 50: Python и Cython

Кеширование проксиобъектов

cdef _Point point_wrap(point_t *x):cdef _Point resultif x.extra != NULL:

return <_Point>x.extraresult = _Point.__new__(_Point)result.inner = xif is_common_point(x):

print ’cache’x.extra = <void *>result

return result

Page 51: Python и Cython

Мои выводы

• python — это удобно;• С — это быстро;• cython объединяет;• все будет хорошо.

Page 52: Python и Cython

Благодарю завнимание

[email protected]/shigin

Page 53: Python и Cython

Вопросы?

[email protected]/shigin