ã絶察çãªå£°æã¯ãã¹ãŠã®æªã®æ ¹æºã§ãã
ããŒã¯ãã©ã³ã¹ã§ãã çãã¯ãªãã質åã ãã§ããã
????èšäºã®èè
ïŒ
zolkkoæé©å
ãœãããŠã§ã¢ã®ã³ã³ããã¹ãã§ã®æé©åã«ã€ããŠè©±ããšããå€ãã®å Žåãããã°ã©ãã®ããã©ãŒãã³ã¹ã®æé©åããœãããŠã§ã¢èªäœã®æé©åãæå³ããŸãã
YAGNIã®åçã«åºã¥ããŠãPythonã¯ããã°ã©ããŒããœãããŠã§ã¢ã®å®è£
ã«éäžã§ããããã«ããäœã¬ãã«ã®ãã®ïŒãªããžã§ã¯ããå²ãåœãŠãããã¡ã¢ãªé åãã¡ã¢ãªã®è§£æŸãèŠçŽã®åŒã³åºãïŒãåŠçããå¿
èŠããªãããŸãã
ãµã€ã¢ã³ã»ãžã§ãŒã³ãºã¯ãHaskell
ã«é¢ãã圌ã®è¬çŸ©ã®1ã€ã§å察ã®åé¡ãææããŸããã 圌ã«ã¯ãã°ã©ããŒã·ã§ã³ã§å¡ãã€ã¶ãããç¢å°ã®ããã¹ã©ã€ãããããŸããã ãNo typesãã¯æåã«ããHaskellãã¯äžå€®ã«ããCoqãã¯æåŸã«æžãããŠããŸãã CoqãæããŠãåœŒã¯æ¬¡ã®ããã«è¿°ã¹ãŸããã ããã§ããïŒ ããã«ã¯å士å·ãå¿
èŠã§ãïŒã[1]ã åè«ã§ãããšããäºå®ã«ãããããããPythonã®ãã³ãã©ã¯ããã®èšèªã®ããã°ã©ããŒã®ãæ°ã«å
¥ãã®æ©èœã®1ã€ã§ãã ç§ã®çµéšã§ã¯ãããã«ããã宿åãå°ãéãçç£ããããšãã§ããŸãã
ãœãããŠã§ã¢ã®æé©åã«é¢ããŠã¯ãããŸããŸãªãœãŒã¹ãããã«ã€ããŠç°ãªãæ¹æ³ã§èªã£ãŠããŸãããç§ã«ãšã£ãŠã¯3ã€ã®ã¬ãã«ã«åããŠããŸãã
- 建ç¯ã¬ãã«
- é«ã¬ãã«ã®ã¢ã«ãŽãªãºã ãšããŒã¿æ§é
- äœã¬ãã«
ããã§è峿·±ãæ©èœã¯ããã§ãïŒæé©åãå®è¡ãããã¬ãã«ãé«ãã»ã©ããã广çã§ãã éåžžã¯ãã®ããã«ã äžæ¹ãæé©åã®ã¬ãã«ãé«ãã»ã©ãæ©ãã«è¡ãå¿
èŠããããŸãããããžã§ã¯ãã®çµããã«ãã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ã®åæ§ç¯ãããå°é£ã«ãªãããšã¯æããã§ãã ãŸããããã«ããã¯ãçºçããå Žæãäºåã«ç¹å®ããããšã¯å°é£ã§ãããŸããèŠä»¶ã倿Žãããå Žåã¯ãœãããŠã§ã¢ã倿Žããããšãé£ãããªããããäžè¬çã«ææå°æ©ãªæé©åãé¿ããããšæããŸãã
ã©ã³ã¿ã€ã æé©å
ããããPythonã³ãŒãã®äœã¬ãã«æé©åã®ããã®æãè«ççã§æ£ããïŒé¢åãªç¹ã§ïŒæŠç¥ã¯ãPyPyãPystonãªã©ã®ç¹å¥ãªããŒã«ã®äœ¿çšã§ãã ããã¯ããã䜿çšãããCpythonã³ãŒãããã§ã«æé©ã§ãããä»»æã®è¡ã远å ããããšãããšãããã©ãŒãã³ã¹ãäœäžããå¯èœæ§ãé«ãããã§ãã ããã«ãPythonã®åçåä»ãã®ãããåŸæ¥ã®æé©åææ³ãé©çšããããšã¯ã§ããŸããã
ç¹ã«ããã®åé¡ã¯Pyston Talk 2015ã§Kevin Modzelewskiã«ãã£ãŠææãããŸãã[2]ã 圌ã«ãããšãçŽ10ïŒ
ã®ã©ã³ã¿ã€ã ãæåŸ
ã§ããŸãã JITããã¬ãŒã¹JITããã¥ãŒãªã¹ãã£ãã¯åæãPystonãªã©ã®ããŸããŸãªææ³ãçµã¿åãããããšã§ãããã©ãŒãã³ã¹ã25ïŒ
åäžãããããšãã§ããŸãã
ãããŠãããã«åœŒã®ã¬ããŒãããåããã1ã€ã®ãã³ãããŒã¯ãã£ãŒãããããŸãïŒ

ã°ã©ãã¯ãããæç¹ã§PyPyãéåžžã®Cpythonããã38åé
ããªãããšã瀺ããŠããŸãã çµæã¯ããã®ãããªããŒã«ã䜿çšããŠãããã©ãŒãã³ã¹ã枬å®ããå¿
èŠãããããšã瀺åããŠããŸãã ãããŠããœãããŠã§ã¢å®è¡ã®å®éã®æ¡ä»¶ã«è¿ãæ¡ä»¶ã§ãå®éã®ããŒã¿ã§ãããè¡ãå¿
èŠããããŸãã ãããŠãéèš³ããŒãžã§ã³ã®æŽæ°ããšã«ãã®ãããªæŒç¿ãå®è¡ããããšããå§ãããŸãã ããã§ã¯ããæé©åãè¡ããããã©ãŒãã³ã¹ã®åäžã確èªããããã®æž¬å®ãè¡ããªãå Žåãã³ãŒããèªã¿ã«ããããããšã ãã確å®ã§ããããšåŒçšã§ããŸã[3]ã
ãœãŒã¹ã³ãŒãã®æé©å
åæ§ã®åé¡ã¯ãèšèªã¬ãã«ã§ã®æé©åäžã«ãæ
£çšçãªéç£ã³ãŒãã䜿çšããŠç¹å®ã§ããŸãã 説æã®ããã«ãåèªã®ãªã¹ããšããã倧æåããåèªã®ãªã¹ãã«å€æãã3ã€ã®é¢æ°ãå®çŸ©ãããŠããå°ããªããã°ã©ã ïŒãŸã£ããæ
£çšçã§ã¯ãªã[4]ïŒã®äŸã瀺ããŸãã
LST = list(map(''.join, product('abc', repeat=10))) def foo(): return map(str.upper, LST) def bar(): res = [] for i in LST: res.append(i.upper()) return res def baz(): return [i.upper() for i in LST]
ãã®äžã§ã3ã€ã®è«ççã«ç䟡ãªé¢æ°ã¯ãæå³çã«ãããã©ãŒãã³ã¹ã«ãããŠãç°ãªããŸãã ãã ããããã©ãŒãã³ã¹ã»ãã³ãã£ã¯ã¹ã¯äœãèšããŸããã ãããã«ãããçµéšã®æµ
ãPythonããã°ã©ããŒã®å Žå-while 1ïŒpass vs whileïŒTrueïŒpass-Python 3ã«åãæ¿ãããšããã«ãªãå±éºæ§ãããéæ³ã
CPythonã¢ãžã¥ãŒã«
Pythonã®äœã¬ãã«æé©åã®ãã1ã€ã®ãªãã·ã§ã³ã¯ãæ¡åŒµã¢ãžã¥ãŒã«ã§ããæ¡åŒµã¢ãžã¥ãŒã«ã«ããžãã¯ã®äžéšãåé€ãããšãäºæž¬çµæã§è¯å¥œãªããã©ãŒãã³ã¹ãéæã§ããå ŽåããããŸãã
ããŒã«ããã
å©çšå¯èœãªPythonããŒã«ã®å€ãã¯ãCUDAã®ã³ãŒãçæããnumpyãŸãã¯C ++ãšã®ééçãªçµ±åãŸã§ãããŸããŸãªæ©èœãæäŸããŸãã ãã ãã以äžã§ã¯ãç¹å¥ã«éžæãããå¢çã®äŸã䜿çšããŠæ¡åŒµã¢ãžã¥ãŒã«ãäœæããã³ã³ããã¹ãã§ã®ã¿åäœãæ€èšããŸãã
def add_mul_two(a, b): acc = 0 i = 0 while i < 1000: acc += a + b i += 1 return acc
ã芧ã®ãšãããCPythonã¯æåéããããå®è¡ããŸãã
12 SETUP_LOOP 40 (to 55) 15 LOAD_FAST 3 (i) 18 LOAD_CONST 2 (1000) 21 COMPARE_OP 0 (<) 24 POP_JUMP_IF_FALSE 54 27 LOAD_FAST 2 (acc) 30 LOAD_FAST 0 (a) 33 LOAD_FAST 1 (b) 36 BINARY_ADD 37 INPLACE_ADD 38 STORE_FAST 2 (acc) 41 LOAD_FAST 3 (i) 44 LOAD_CONST 3 (1) 47 INPLACE_ADD 48 STORE_FAST 3 (i) 51 JUMP_ABSOLUTE 15 54 POP_BLOCK
Cã§æãåçŽãªæ¡åŒµã¢ãžã¥ãŒã«ãèšè¿°ããããšã«ãããç¶æ³ãä¿®æ£ã§ããŸãã
ãããè¡ãã«ã¯ãæå°ã¢ãžã¥ãŒã«åæå颿°ã決å®ããŸãã
// example.c void initexample(void) { Py_InitModule("example", NULL); }
ãã®é¢æ°ã¯ãå®éã«importã¹ããŒãã¡ã³ããå®è¡ããŠããããããã®ããã«åŒã³åºãããŸã...
import example IMPORT_NAME 0 (example) STORE_FAST 0 (example)
...ãã«ãã£ã«ã¡ã³ãã«ã€ãªãããŸã...
// ceval.c ... w = GETITEM(names, oparg); v = PyDict_GetItemString(f->f_builtins, "__import__"); ... x = PyEval_CallObject(v, w); ...
...çµã¿èŸŒã¿é¢æ°builtin___import__ïŒbltinmodule.cïŒãããã«åŒã³åºããã§ãŒã³ã®äžæµïŒ
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, const char *pathname, FILE *fp) { char funcname[258]; PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); return dl_loadmod(Py_GetProgramName(), pathname, funcname); }
ãããã«ãããäžéšã®ãã©ãããã©ãŒã ããã³ç¹å®ã®æ¡ä»¶äžã§ã¯ïŒCPythonã¯åçã«ããŒããããæ¡åŒµã¢ãžã¥ãŒã«ããµããŒãããŠæ§ç¯ãããã¢ãžã¥ãŒã«ã¯ãŸã ããŒããããŠããŸãããã¢ãžã¥ãŒã«ãã¡ã€ã«åã«ã¯ç¹å®ã®ãã©ãããã©ãŒã åºæã®æ¡åŒµããããŸãã
次ã«ãã¢ãžã¥ãŒã«ã¡ãœãããæ±ºå®ãã......
static PyObject * add_mul_two(PyObject * self, PyObject * args); static PyMethodDef ExampleMethods[] = { {"add_mul_two", add_mul_two, METH_VARARGS, ""}, {NULL, NULL, 0, NULL} }; void initexample(void) { Py_InitModule("example", ExampleMethods); }
...ããã³ãã®å®è£
èªäœã ãã®å Žåãå
¥å倿°ã®ã¿ã€ãã¯æ£ç¢ºã«ããã£ãŠããããã颿°ã¯æ¬¡ã®ããã«å®çŸ©ã§ããŸãã
PyObject * add_mul_two(PyObject * self, PyObject * args) { int a, b, acc = 0; if (!PyArg_ParseTuple(args, "ii", &a, &b)) { PyErr_SetNone(PyExc_ValueError); return NULL; } for (int i = 0; i < 1000; i++) acc += a + b; return Py_BuildValue("i", acc); }
åºåã¯ãNumbaã䜿çšããŠååŸã§ãããã®ãšã»ãŒåããã€ããªã³ãŒãã«ãªããŸã...
___main__.add_mul_two$1.int32.int32: addl %r8d, %ecx imull $1000, %ecx, %eax movl %eax, (%rdi) xorl %eax, %eax retq
...ãããã2è¡ã ããèšè¿°ãã1ã€ã®ããã°ã©ãã³ã°èšèªã®å¶éãè¶
ããªãããã«ããŸãã
@jit(int32(int32, int32), nopython=True)
ãã®ã³ãŒãã«å ããŠãnumbaã¯ä»¥äžãçæããŸã
add_mul_two.inspect_asm().values()[0].decode('string_escape')
...次ã®åœ¢åŒã®ã©ãããŒé¢æ°ïŒ
_wrapper.__main__.add_mul_two$1.int32.int32: ... movq %rdi, %r14 movabsq $_.const.add_mul_two, %r10 movabsq $_PyArg_UnpackTuple, %r11 ... movabsq $_PyNumber_Long, %r15 callq *%r15 movq %rax, %rbx xorl %r14d, %r14d testq %rbx, %rbx je LBB1_8 movabsq $_PyLong_AsLongLong, %rax âŠ
ãã®ã¿ã¹ã¯ã¯ããã³ã¬ãŒã¿ã«èšè¿°ãããŠãã眲åã«åŸã£ãŠå
¥ååŒæ°ãè§£æããæåããå Žåãã³ã³ãã€ã«ãããããŒãžã§ã³ãå®è¡ããããšã§ãã ãã®æ¹æ³ã¯éåžžã«é
åçã§ãããããšãã°ãå¥ã®é¢æ°ã§ã«ãŒãã®æ¬äœãåãåºãå Žåã¯ããã³ã¬ãŒã¿ã§ãã¬ãŒã åããããnopythonãç¡å¹ã«ããå¿
èŠããããŸãã
Cythonã¯æ¬¡ã®ææŠè
ã§ãã ããã¯ãC颿°ã®åŒã³åºããšCåã®å®çŸ©ããµããŒãããPythonã®ã¹ãŒããŒã»ããã§ãã ãããã£ãŠãæãåçŽãªå Žåããã®add_mul_two颿°ã¯Cpythonã«äŒŒãŠããŸãã ãã ããåºç¯ãªæ©èœã¯ãã®ããã«ã¯æäŸããããCããŒãžã§ã³ãšã¯ç°ãªããçµæã®ãã¡ã€ã«ã¯CPython APIã¿ã€ãã®ã»ãŒ2,000è¡ã«ãªããŸãã
__pyx_t_2 = PyNumber_Add(__pyx_v_a, __pyx_v_b); if (unlikely(!__pyx_t_2)) { __pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error; } __Pyx_GOTREF(__pyx_t_2); __pyx_t_3 = PyNumber_InPlaceAdd(__pyx_v_acc, __pyx_t_2); if (unlikely(!__pyx_t_3)) { __pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error; }
ã³ãŒãã®éãšããç¹ã§ã¯ãªããç¹ç°æ§ã®ç¹ã§ç¶æ³ãæ¹åããã«ã¯ãããšãã°Cã§ã®é¢æ°èªäœã®å®è£
ãèšè¿°ããCythonã䜿çšããŠã©ãããŒã決å®ããŸãã
int cadd_mul_two(int a, int b) { int32_t acc = 0; for (int i = 0; i < 1000; i++) acc += a + b; return acc; } cdef extern from "example_func.h": int cadd_mul_two(int, int) def add_two(a, b): return cadd_two(a, b) cythonize("sample.pyx", sources=[ 'example_func.c' ])
...ã»ãŒå®ç§ãªãªãã·ã§ã³ãåŸãããŸããããã®å Žåã¯ãã§ã«CãCythonãPythonã§èšè¿°ããå¿
èŠããããŸãã
__pyx_t_1 = __Pyx_PyInt_As_int32_t(__pyx_v_a); if (unlikely((__pyx_t_1 == (int32_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_ __pyx_t_2 = __Pyx_PyInt_As_int32_t(__pyx_v_b); if (unlikely((__pyx_t_2 == (int32_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_ __pyx_t_3 = __Pyx_PyInt_From_int32_t(cadd_two(__pyx_t_1, __pyx_t_2)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; _
ãã³
Rustã§ã¢ãžã¥ãŒã«ãäœæããã«ã¯ãno_mangleã§extern颿°ã宣èšããå¿
èŠããããŸã...
...ã¿ã€ãã説æããŸãã
type PyCFunction = unsafe extern "C" fn (slf: *mut isize, args: *mut isize) -> *mut isize;
Cãšåæ§ã«ãPyMethodã宣èšããå¿
èŠããããŸãã
lazy_static! { static ref METHODS: Vec = { vec![ PyMethodDef { ml_name: &ADD_MUL_TWO[0] as *const _, ml_meth: Some(add_mul_two), }, ... ] }; }
CPythonã«ã¯å€ãã®C APIåŒã³åºããããããããããèšè¿°ããå¿
èŠããããŸãã
ããããæçµçã«ã¯ããŸãã«ãã®ãããªçŸããæ©èœãåŸãããŸãã
ãŸãã¯ãå¿
èŠã«å¿ããŠ...
let acc: i32 = (0..).take(1000) .map(|_| a + b) .fold(0, |acc, x| acc + x);
...ãã®é¢æ°ã2ã€ã®ãã·ã³åœä»€ã«ã³ã³ãã€ã«ãããŸãã
__ZN7add_mul_two20h391818698d43ab0ffcaE: ... callq 0x7a002
ãã®ã¢ãããŒãã®æ¬ ç¹ã¯æ¬¡ã®ãšããã§ãã
- CPython API 2.7ã®ã¿ãPython3ãå¿
èŠãªå Žåã¯ãå€ãã®ã³ãŒããè€è£œããå¿
èŠããããŸãã
- no_stdãåå ã§ãã€ããªã®ãµã€ãºãå°ããããããšãããšãã³ãŒããå¢ããŸã
- ãå«ã Rustã®å€ãã®ããŒã¿æ§é ã¯Cãšã¯ç°ãªããŸããããšãã°ãRustã¯pascalæååã䜿çšããŸããCãšå¯Ÿè©±ããã«ã¯ãstd :: ffi :: CStringã®ãããªãã®ã䜿çšããå¿
èŠããããŸãã
ãããã幞ããªããšã«ãå¿
èŠãªãã¹ãŠã®CpythonAPIãæ¢ã«èª¬æããŠããã ãã§ãªãããããã«é«ã¬ãã«ã®æœè±¡åãæäŸããåæã«Python 2.xããã³3.xããµããŒãããçŽ æŽãããrust-cpythonãããžã§ã¯ãããããŸãã ã³ãŒãã¯æ¬¡ã®ãããªãã®ã§ãã
[package] name = "example" version = "0.1.0" [lib] name = "example" crate-type = ["dylib"] [dependencies] interpolate_idents = "0.0.9" [dependencies.cpython] version = "0.0.5" default-features = false features = ["python27-sys"]
py_module_initializer!(example, |py, module| { try!(module.add(py, "add_two", py_fn!(add_two))); Ok(()) });
å®éã«ã¯ãsclice_pattensããã³PyTuple.as_sliceã«å¯ŸããŠã®ã¿ãå€éã®Rustã䜿çšããŸãã
ããããç§ã®æèŠã§ã¯ããã®ç¶æ³ã§ã®Rustã¯ã匷åã§é«ã¬ãã«ã®æœè±¡åãã¢ã«ãŽãªãºã ãšããŒã¿æ§é ã®åŸ®èª¿æŽæ©èœã广çã§äºæž¬å¯èœãªæé©åçµæãåãããœãªã¥ãŒã·ã§ã³ãæäŸããŸãã ã€ãŸããä»ã®ããŒã«ã«ä»£ãã䟡å€ã®ããéžæè¢ã®ããã«èŠããŸãã
ãã®èšäºã§äœ¿çšãããŠãããµã³ãã«ã³ãŒãã衚瀺ã§ããŸã
ãã¡ã ã
æžèª
1ïŒãµã€ã¢ã³ãã€ãã³ãžã§ãŒã³ãºãHaskellã§ã®ã¿ã€ãã®åéº-ãµã€ã¢ã³ãã€ãã³ãžã§ãŒã³ãºïŒè¬çŸ©2ïŒã2014幎ã
youtu.be / brE_dyedGm0ïŒt = 5362ïŒKevin Modzelewskiã2015/11/10 Pyston Meetupã2015ã
www.youtube.com / watchïŒv = NdB9XoBg5zI
3ïŒMartin FowlerãYet Another OptimizationArticleã2002ã
martinfowler.com / ieeeSoftware / yetOptimization.pdf4ïŒã¬ã€ã¢ã³ãã»ãããã£ã³ã¬ãŒãã³ãŒããçŸãããæ
£çšçãªPythonã«å€æã2013幎ã
www.youtube.com / watchïŒv = OSGv2VnC0go