Upload
archibald-barrett
View
239
Download
0
Embed Size (px)
Citation preview
MilOSS-il 2012שיאון שחורי
מוטיבציה
python זה קל ו C?זה מהיר. למה לא לשלב יש כבר קוד קיים בC אנחנו רוצים .
להשתמש בו, ולבסס מעליו קוד חדש ב python
מסקנה: צריך ממשק )דו כיווני( ביןpython ל C
פתרונות ידועים )לי(: שימוש בתהליכיםcython או ctypes, C/Python APIנפרדים,
פתרונות )תהליכים(
תהליכים שונים אחד כתוב בC השני ב ,python העברת מידע באמצעותIO( socket)'קבצים וכו ,
?מה קיבלנו לא צריך להכיר טכנולוגיה חדשה צריך לנהל תהליךC מלא לא יעיל מסורבלצריך להגדיר ממשקים בין התהליכים
(ctypesפתרונות )
יצירתdll ושימוש ב ctypes כתיבתdynamic library ב C טעינה של הספרייה באמצעותctypes קריאה לפונקציות שנכתבו בC
(ctypesפתרונות )
?מה קיבלנו תהליך בודד יעיל קל )הגדרות כפולות )ולאו דווקא תואמות קישוריות חד כיוונית )אי אפשר לקרוא לקוד
python מתוך C )בקלות
(C/Python APIפתרונות ) שימוש בC/Python API
קידוד קוד בC תוך קריאה לפונקציות מתוך Python.h
בנייתextension באמצעות distutils שימוש מתוך פייתון באמצעותimport
?מה קיבלנו תהליך בודד יעיל הגדרת טיפוסים בודדת קישוריות דו כיווניות קידוד מסורבל )למשל, שימוש באובייקטים פייתונים
C )מתוך
(Cythonפתרונות ) שימוש בCython
מבוססpyrex. כתיבת קבציpyx קבצי :python פחות או יותר( עם(
פקודות מיוחדות בנייתextension באמצעות distutils שימוש מתוך פייתון באמצעותimport
?מה קיבלנו תהליך בודד יעיל הגדרת טיפוסים בודדת כמעט() קישוריות דו כיווניות קידוד נוח
Cythonבסיסי #include <stdio.h>
inline int my_func(int x){ printf(“my func %d\n”, x); return 0;}
cdef extern from “bla.h”: int my_func(int) def pymy_func(x): return my_func(x)
import blaprint bla.pymy_func(10)
bla.h
bla.pyx
main.py
Distutils setup.pyfrom distutils.core import setupfrom distutils.extension import Extensionfrom Cython.Distutils import build_ext
setup(cmdclass={'build_ext': build_ext}, ext_modules=[Extension(“bla", ['bla.pyx'])])
setup.py
$ python setup.py build_ext --inplacerunning build_extcythoning bla.pyx to bla.cbuilding 'bla' extensiongcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.6 -c bla.c -o build/temp.linux-i686-2.6/bla.ogcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions build/temp.linux-i686-2.6/bla.o -o /mnt/filer_home/users/t_sion/bla.so
בנייה
דוגמה: קידוד פשוט
הבעיה: יש מערך גדול של בתים, ורוציםלקודד אותו עם הקוד הפשוט הבא: כל בית
notמוחלף בשני בתים: הבית המקורי וה שלו
מימוש פייתוניimport array
lookup = {}
for i in range(256): lookup[chr(i)] = chr(i) + chr(i ^ 0xFF)
def encode(arr): out = array.array('c', '\x00' * len(arr) * 2) for i in xrange(len(arr)): data = lookup[arr[i]] out[2*i] = data[0] out[2*i + 1] = data[1]
return out
pyencode.py
מימוש פייתוני - המשך
In [10]: s = array.array('c', '\x01\xf3\x34\x45' * (10 ** 6))
In [11]: import pyencode
In [12]: %timeit -n 3 pyencode.encode(s)3 loops, best of 3: 2.84 s per loop
פשוטcythonמימוש
In [13]: import cyencode_simple
In [14]: %timeit -n 3 cyencode_simple.encode(s)3 loops, best of 3: 1.62 s per loop
אותו קוד, רק מקומפל עםcython למודול cyencode_simple
מתקדםcythonמימוש import arraycdef unsigned short lookup[256]cdef unsigned char *_ptrfor i in range(256): _ptr = <unsigned char*>(&lookup[i]) _ptr[0] = <int>i _ptr[1] = <int>(i ^ 0xFF)
def encode(arr): cdef int i cdef unsigned char *in_ptr, *out_ptr, *p in_ptr = <unsigned char*><unsigned int>(arr.buffer_info()[0]) out = array.array('c', '\x00' * len(arr) * 2) out_ptr = <unsigned char*><unsigned int>(out.buffer_info()[0]) for i in range(len(arr)): p = <unsigned char*>(&lookup[<int>in_ptr[i]]) out_ptr[2*i] = p[0] out_ptr[2*i + 1] = p[1] return out
cyencode.py
מתקדם - cythonמימוש המשך
In [15]: import cyencode
In [16]: %timeit -n 3 cyencode.encode(s)3 loops, best of 3: 26.8 ms per loop
C מתקדם – הצצה לקוד cythonמימוש for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_4; __pyx_t_6+=1) { __pyx_v_i = __pyx_t_6;
/* "cyencode.pyx":17 * p = <unsigned char*>(&lookup[<int>in_ptr[i]]) # <<<<<<< */ __pyx_v_p = ((unsigned char *)(&(__pyx_v_8cyencode_lookup[ ((int)(__pyx_v_in_ptr[__pyx_v_i]))])));
/* "cyencode.pyx":18 * out_ptr[2*i] = p[0] # <<<<<<< */ (__pyx_v_out_ptr[(2 * __pyx_v_i)]) = (__pyx_v_p[0]);
/* "cyencode.pyx":19 * out_ptr[2*i + 1] = p[1] # <<<<<<< */ (__pyx_v_out_ptr[((2 * __pyx_v_i) + 1)]) = (__pyx_v_p[1]); }
cyencode.c
Pitfalls
GILReference counting טיפול בשגיאות בcdef functions
פיצ'רים נוספים
def,cdef,cpdefnamespaces איך לתת שמות זהים –
Cבפייתון וב . קבציpxdcinit ו dealloc אינטגרציה עםnumpy
מידע נוסף
תיעודcython :http://docs.cython.org כוללtutorialטוב
:במייל שליsion.schori@gmail