Presentation is loading. Please wait.

Presentation is loading. Please wait.

שיאון שחוריMilOSS-il 2012. מוטיבציה  python זה קל ו C זה מהיר. למה לא לשלב?  יש כבר קוד קיים ב C. אנחנו רוצים להשתמש בו, ולבסס מעליו קוד חדש ב python.

Similar presentations


Presentation on theme: "שיאון שחוריMilOSS-il 2012. מוטיבציה  python זה קל ו C זה מהיר. למה לא לשלב?  יש כבר קוד קיים ב C. אנחנו רוצים להשתמש בו, ולבסס מעליו קוד חדש ב python."— Presentation transcript:

1 שיאון שחוריMilOSS-il 2012

2 מוטיבציה  python זה קל ו C זה מהיר. למה לא לשלב?  יש כבר קוד קיים ב C. אנחנו רוצים להשתמש בו, ולבסס מעליו קוד חדש ב python  מסקנה: צריך ממשק (דו כיווני) בין python ל C  פתרונות ידועים (לי): שימוש בתהליכים נפרדים, ctypes, C/Python API או cython

3 פתרונות ( תהליכים )  תהליכים שונים אחד כתוב ב C, השני ב python העברת מידע באמצעות IO (socket, קבצים וכו')  מה קיבלנו? לא צריך להכיר טכנולוגיה חדשה צריך לנהל תהליך C מלא  לא יעיל  מסורבל  צריך להגדיר ממשקים בין התהליכים 

4 פתרונות (ctypes)  יצירת dll ושימוש ב ctypes כתיבת dynamic library ב C טעינה של הספרייה באמצעות ctypes קריאה לפונקציות שנכתבו ב C

5 פתרונות (ctypes)  מה קיבלנו? תהליך בודד יעיל קל הגדרות כפולות (ולאו דווקא תואמות)  קישוריות חד כיוונית (אי אפשר לקרוא לקוד python מתוך C בקלות) 

6 פתרונות (C/Python API)  שימוש ב C/Python API קידוד קוד ב C תוך קריאה לפונקציות מתוך Python.h בניית extension באמצעות distutils שימוש מתוך פייתון באמצעות import  מה קיבלנו? תהליך בודד יעיל הגדרת טיפוסים בודדת קישוריות דו כיווניות קידוד מסורבל (למשל, שימוש באובייקטים פייתונים מתוך C) 

7 פתרונות (Cython)  שימוש ב Cython מבוסס pyrex כתיבת קבצי.pyx: קבצי python (פחות או יותר) עם פקודות מיוחדות בניית extension באמצעות distutils שימוש מתוך פייתון באמצעות import  מה קיבלנו? תהליך בודד יעיל הגדרת טיפוסים בודדת (כמעט  ) קישוריות דו כיווניות קידוד נוח

8 Cython בסיסי #include 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 bla print bla.pymy_func(10) bla.h bla.pyx main.py

9 Distutils setup.py from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext setup(cmdclass={'build_ext': build_ext}, ext_modules=[Extension(“bla", ['bla.pyx'])]) setup.py $ python setup.py build_ext --inplace running build_ext cythoning bla.pyx to bla.c building 'bla' extension gcc -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.o gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions build/temp.linux- i686-2.6/bla.o -o /mnt/filer_home/users/t_sion/bla.so בנייה

10 דוגמה : קידוד פשוט  הבעיה: יש מערך גדול של בתים, ורוצים לקודד אותו עם הקוד הפשוט הבא: כל בית מוחלף בשני בתים: הבית המקורי וה not שלו

11 מימוש פייתוני 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

12 מימוש פייתוני - המשך 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

13 מימוש 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

14 מימוש cython מתקדם import array cdef unsigned short lookup[256] cdef unsigned char *_ptr for i in range(256): _ptr = (&lookup[i]) _ptr[0] = i _ptr[1] = (i ^ 0xFF) def encode(arr): cdef int i cdef unsigned char *in_ptr, *out_ptr, *p in_ptr = (arr.buffer_info()[0]) out = array.array('c', '\x00' * len(arr) * 2) out_ptr = (out.buffer_info()[0]) for i in range(len(arr)): p = (&lookup[ in_ptr[i]]) out_ptr[2*i] = p[0] out_ptr[2*i + 1] = p[1] return out cyencode.py

15 מימוש cython מתקדם - המשך In [15]: import cyencode In [16]: %timeit -n 3 cyencode.encode(s) 3 loops, best of 3: 26.8 ms per loop

16 מימוש cython מתקדם – הצצה לקוד C 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 = (&lookup[ 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

17 Pitfalls  GIL  Reference counting  טיפול בשגיאות ב cdef functions

18 פיצ ' רים נוספים  def,cdef,cpdef  namespaces – איך לתת שמות זהים בפייתון וב C  קבצי.pxd  cinit ו dealloc  אינטגרציה עם numpy

19 מידע נוסף  תיעוד cython: http://docs.cython.orghttp://docs.cython.org כולל tutorial טוב  במייל שלי: sion.schori@gmail

20 נספח : דוגמה ל cytpes  נשתמש ב ספריה librt  נייצא את הפונרציה clock_gettime לפייתון

21 נספח : דוגמה ל ctypes RT_DLL = ctypes.cdll.LoadLibrary(‘/lib/librt.so.1’) # taken from bits/time.h CLOCK_MONOTONIC = 1 class timespec(ctypes.Structure): _fields_ = [('tv_sec', ctypes.c_long), ('tv_nsec', ctypes.c_long)] def gettime(): time_struct = timespec() res = RT_DLL.clock_gettime(CLOCK_MONOTONIC, ctypes.addressof(time_struct)) if res != 0: raise RuntimeError("clock_gettime failed (err = %d)" % (ctypes.get_errno(),)) return time_struct.tv_sec + time_struct.tv_nsec * 1e-9


Download ppt "שיאון שחוריMilOSS-il 2012. מוטיבציה  python זה קל ו C זה מהיר. למה לא לשלב?  יש כבר קוד קיים ב C. אנחנו רוצים להשתמש בו, ולבסס מעליו קוד חדש ב python."

Similar presentations


Ads by Google