שיאון שחוריmiloss-il 2012. מוטיבציה python זה קל ו c זה מהיר. למה...

Post on 19-Jan-2016

239 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

top related