Download presentation
Presentation is loading. Please wait.
Published byArchibald Barrett Modified over 8 years ago
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
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.