Wednesday, November 2, 2016

Simple numpy and Cython example

In [1]:
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:50% !important; }</style>"))
In [2]:
%load_ext cython
In [4]:
# Pass compile options to %%cython
# -a means annotate the source code to show sections
# which have Python interaction
In [6]:
%%cython -a
cimport numpy as np


cdef double _dot(double* a, double* b, int n):
    cdef int i
    cdef double sum


    sum = 0
    for i in range(n):
        sum += a[i] * b[i]
    
    return sum


cpdef double cy_dot(np.ndarray a, np.ndarray b):
    cdef int n = a.shape[0]

    cdef double* a_ptr = <double*> a.data
    cdef double* b_ptr = <double*> b.data

    return _dot(a_ptr, b_ptr, n)
Out[6]:
Cython: _cython_magic_3e017d4f9980d56ce613de0b5ec2e832.pyx

Generated by Cython 0.23.4

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

+01: cimport numpy as np
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 02: 
 03: 
+04: cdef double _dot(double* a, double* b, int n):
static double __pyx_f_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832__dot(double *__pyx_v_a, double *__pyx_v_b, int __pyx_v_n) {
  int __pyx_v_i;
  double __pyx_v_sum;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_dot", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 05:     cdef int i
 06:     cdef double sum
 07: 
 08: 
+09:     sum = 0
  __pyx_v_sum = 0.0;
+10:     for i in range(n):
  __pyx_t_1 = __pyx_v_n;
  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
    __pyx_v_i = __pyx_t_2;
+11:         sum += a[i] * b[i]
    __pyx_v_sum = (__pyx_v_sum + ((__pyx_v_a[__pyx_v_i]) * (__pyx_v_b[__pyx_v_i])));
  }
 12: 
+13:     return sum
  __pyx_r = __pyx_v_sum;
  goto __pyx_L0;
 14: 
 15: 
+16: cpdef double cy_dot(np.ndarray a, np.ndarray b):
static PyObject *__pyx_pw_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832_1cy_dot(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static double __pyx_f_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832_cy_dot(PyArrayObject *__pyx_v_a, PyArrayObject *__pyx_v_b, CYTHON_UNUSED int __pyx_skip_dispatch) {
  int __pyx_v_n;
  double *__pyx_v_a_ptr;
  double *__pyx_v_b_ptr;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("cy_dot", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832_1cy_dot(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyObject *__pyx_pw_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832_1cy_dot(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyArrayObject *__pyx_v_a = 0;
  PyArrayObject *__pyx_v_b = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("cy_dot (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_a,&__pyx_n_s_b,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_a)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        case  1:
        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_b)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("cy_dot", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "cy_dot") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_a = ((PyArrayObject *)values[0]);
    __pyx_v_b = ((PyArrayObject *)values[1]);
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("cy_dot", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
  __pyx_L3_error:;
  __Pyx_AddTraceback("_cython_magic_3e017d4f9980d56ce613de0b5ec2e832.cy_dot", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_a), __pyx_ptype_5numpy_ndarray, 1, "a", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_b), __pyx_ptype_5numpy_ndarray, 1, "b", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __pyx_r = __pyx_pf_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832_cy_dot(__pyx_self, __pyx_v_a, __pyx_v_b);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832_cy_dot(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_a, PyArrayObject *__pyx_v_b) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("cy_dot", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyFloat_FromDouble(__pyx_f_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832_cy_dot(__pyx_v_a, __pyx_v_b, 0)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("_cython_magic_3e017d4f9980d56ce613de0b5ec2e832.cy_dot", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+17:     cdef int n = a.shape[0]
  __pyx_v_n = (__pyx_v_a->dimensions[0]);
 18: 
+19:     cdef double* a_ptr = <double*> a.data
  __pyx_v_a_ptr = ((double *)__pyx_v_a->data);
+20:     cdef double* b_ptr = <double*> b.data
  __pyx_v_b_ptr = ((double *)__pyx_v_b->data);
 21: 
+22:     return _dot(a_ptr, b_ptr, n)
  __pyx_r = __pyx_f_46_cython_magic_3e017d4f9980d56ce613de0b5ec2e832__dot(__pyx_v_a_ptr, __pyx_v_b_ptr, __pyx_v_n);
  goto __pyx_L0;
In [5]:
import numpy as np
a = np.array([-2., 0., 5.])
b = np.array([1., 1., 1.])
print a.dot(b)
3.0
In [8]:
print cy_dot(a, b)
3.0

No comments :

Post a Comment