{ "cells": [ { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import ctypes\n", "import math as m\n", "from ctypes.util import find_library" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# Windows .dll\n", "# Linux .so" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0.8414709848078965, 0.8414709848078965)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "libm = ctypes.CDLL(find_library('m'))\n", "csin = libm.sin\n", "csin.restype = ctypes.c_double\n", "x = ctypes.c_double(1.0)\n", "csin(x), m.sin(1.0)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "322 ns ± 2.69 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n", "131 ns ± 0.565 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)\n" ] } ], "source": [ "x_c = ctypes.c_double(1.0)\n", "x_py = 1.0\n", "%timeit csin(x_c)\n", "%timeit m.sin(x_py)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Mon Dec 14 13:25:33 2020'" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from time import ctime\n", "libc = ctypes.CDLL(find_library('c'))\n", "ctime(libc.time(None))" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "59.3 ms ± 187 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n", "62 ms ± 3.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], "source": [ "from cymodule.pymodule import golden_ratio as cythonize_golden_ratio\n", "%timeit cythonize_golden_ratio(1_000_000)\n", "\n", "from pymodule import golden_ratio as golden_ratio\n", "%timeit golden_ratio(1_000_000)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.0\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_a25cc206250de381ca3f21379ccb32a8.pyx\n", " \n", "\n", "\n", "

Generated by Cython 0.29.15

\n", "

\n", " Yellow lines hint at Python interaction.
\n", " Click on a line that starts with a \"+\" to see the C code that Cython generated for it.\n", "

\n", "
 1: 
\n", "
+2: def f(x):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_a25cc206250de381ca3f21379ccb32a8_1f(PyObject *__pyx_self, PyObject *__pyx_v_x); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_a25cc206250de381ca3f21379ccb32a8_1f = {\"f\", (PyCFunction)__pyx_pw_46_cython_magic_a25cc206250de381ca3f21379ccb32a8_1f, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_a25cc206250de381ca3f21379ccb32a8_1f(PyObject *__pyx_self, PyObject *__pyx_v_x) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"f (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_a25cc206250de381ca3f21379ccb32a8_f(__pyx_self, ((PyObject *)__pyx_v_x));\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_a25cc206250de381ca3f21379ccb32a8_f(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_x) {\n",
       "  double __pyx_v_y;\n",
       "  double __pyx_v_z;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"f\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_1);\n",
       "  __Pyx_XDECREF(__pyx_t_2);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_a25cc206250de381ca3f21379ccb32a8.f\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = PyTuple_Pack(3, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_z); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 2, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_a25cc206250de381ca3f21379ccb32a8_1f, NULL, __pyx_n_s_cython_magic_a25cc206250de381ca); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_f, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_jovyan_cache_ipython_cytho, __pyx_n_s_f, 2, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 2, __pyx_L1_error)\n",
       "
+3:     cdef double y = 1.0
\n", "
  __pyx_v_y = 1.0;\n",
       "
+4:     cdef double z = x + y
\n", "
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_2 = PyNumber_Add(__pyx_v_x, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_v_z = __pyx_t_3;\n",
       "
+5:     return z
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_z); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 5, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_r = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "  goto __pyx_L0;\n",
       "
 6: 
\n", "
+7: print(f(2))
\n", "
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_f); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython --annotate\n", "\n", "def f(x):\n", " cdef double y = 1.0\n", " cdef double z = x + y\n", " return z\n", "\n", "print(f(2))" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Compiling /home/jovyan/work/cy_golden_ratio.pyx because it changed.\n", "[1/1] Cythonizing /home/jovyan/work/cy_golden_ratio.pyx\n", "running build_ext\n", "building 'cy_golden_ratio' extension\n", "creating /home/jovyan/work/tmp9biydcrw/home\n", "creating /home/jovyan/work/tmp9biydcrw/home/jovyan\n", "creating /home/jovyan/work/tmp9biydcrw/home/jovyan/work\n", "gcc -pthread -B /opt/conda/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/opt/conda/include/python3.7m -c /home/jovyan/work/cy_golden_ratio.cpp -o /home/jovyan/work/tmp9biydcrw/home/jovyan/work/cy_golden_ratio.o\n", "\u001b[01m\u001b[Kcc1plus:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kcommand line option ‘\u001b[01m\u001b[K-Wstrict-prototypes\u001b[m\u001b[K’ is valid for C/ObjC but not for C++\n", "g++ -pthread -shared -B /opt/conda/compiler_compat -L/opt/conda/lib -Wl,-rpath=/opt/conda/lib -Wl,--no-as-needed -Wl,--sysroot=/ /home/jovyan/work/tmp9biydcrw/home/jovyan/work/cy_golden_ratio.o -o /home/jovyan/work/cy_golden_ratio.cpython-37m-x86_64-linux-gnu.so\n" ] } ], "source": [ "! cythonize -3 -a -i cy_golden_ratio.pyx" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "20.1 ms ± 529 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "from cy_golden_ratio import golden_ratio as cy_golden_ratio\n", "%timeit cy_golden_ratio(1_000_000)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "19.7 ms ± 805 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "from cy_golden_ratio import golden_ratio as cy_golden_ratio\n", "%timeit cy_golden_ratio(1_000_000)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "# f2py" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "# SWIG" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "# C++: Boost::Python" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "# Rust + PyO3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "# SciPy lowlevel callable" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" } }, "nbformat": 4, "nbformat_minor": 4 }