In [3]:
%load_ext Cython


The Cython extension is already loaded. To reload it, use:
  %reload_ext Cython

In [36]:
def af(_x):
    _x += 1
    return _x

x = np.ones(100000)
%timeit af(x)


45.9 µs ± 804 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

OK, that's what we have to beat ..


In [37]:
%%cython
import cython
import numpy as np
cimport numpy as np
# These imports have to be in the same cell as the function and must be prefaced
# with %%cython

@cython.boundscheck(False)
@cython.wraparound(False)
def add1(double[:] x):
    cdef unsigned long i
    for i in range(x.size):
        x[i] += 1

In [38]:
x = np.ones(100000)
%timeit add1(x)


60.6 µs ± 2.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Huh


In [40]:
%%cython --annotate
import cython
import numpy as np
cimport numpy as np
# These imports have to be in the same cell as the function and must be prefaced
# with %%cython

@cython.boundscheck(False)
@cython.wraparound(False)
def add1(double[:] x):
    cdef unsigned long i
    for i in range(x.size):
        x[i] += 1


Out[40]:
Cython: _cython_magic_dec9140e268619ff30bd3b75cd97ba32.pyx

Generated by Cython 0.24.1

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: import cython
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+02: import numpy as np
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 03: cimport numpy as np
 04: # These imports have to be in the same cell as the function and must be prefaced
 05: # with %%cython
 06: 
 07: @cython.boundscheck(False)
 08: @cython.wraparound(False)
+09: def add1(double[:] x):
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_dec9140e268619ff30bd3b75cd97ba32_1add1(PyObject *__pyx_self, PyObject *__pyx_arg_x); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_dec9140e268619ff30bd3b75cd97ba32_1add1 = {"add1", (PyCFunction)__pyx_pw_46_cython_magic_dec9140e268619ff30bd3b75cd97ba32_1add1, METH_O, 0};
static PyObject *__pyx_pw_46_cython_magic_dec9140e268619ff30bd3b75cd97ba32_1add1(PyObject *__pyx_self, PyObject *__pyx_arg_x) {
  __Pyx_memviewslice __pyx_v_x = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("add1 (wrapper)", 0);
  assert(__pyx_arg_x); {
    __pyx_v_x = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_arg_x); if (unlikely(!__pyx_v_x.memview)) __PYX_ERR(0, 9, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("_cython_magic_dec9140e268619ff30bd3b75cd97ba32.add1", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_46_cython_magic_dec9140e268619ff30bd3b75cd97ba32_add1(__pyx_self, __pyx_v_x);

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_dec9140e268619ff30bd3b75cd97ba32_add1(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_x) {
  unsigned long __pyx_v_i;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("add1", 0);
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("_cython_magic_dec9140e268619ff30bd3b75cd97ba32.add1", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __PYX_XDEC_MEMVIEW(&__pyx_v_x, 1);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__20 = PyTuple_Pack(3, __pyx_n_s_x, __pyx_n_s_x, __pyx_n_s_i); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__20);
  __Pyx_GIVEREF(__pyx_tuple__20);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_dec9140e268619ff30bd3b75cd97ba32_1add1, NULL, __pyx_n_s_cython_magic_dec9140e268619ff30); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_add1, __pyx_t_1) < 0) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__21 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_kghose_ipython_cython__cy, __pyx_n_s_add1, 9, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__21)) __PYX_ERR(0, 9, __pyx_L1_error)
 10:     cdef unsigned long i
+11:     for i in range(x.size):
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_x, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_long(__pyx_t_2); if (unlikely((__pyx_t_3 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
    __pyx_v_i = __pyx_t_4;
+12:         x[i] += 1
    __pyx_t_5 = __pyx_v_i;
    *((double *) ( /* dim=0 */ (__pyx_v_x.data + __pyx_t_5 * __pyx_v_x.strides[0]) )) += 1.0;
  }

In [41]:
%%cython --annotate
import cython
import numpy as np
cimport numpy as np
# These imports have to be in the same cell as the function and must be prefaced
# with %%cython

@cython.boundscheck(False)
@cython.wraparound(False)
def add2(double[:] x):
    cdef unsigned long i, N = x.size
    for i in range(N):
        x[i] += 1


Out[41]:
Cython: _cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9.pyx

Generated by Cython 0.24.1

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: import cython
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+02: import numpy as np
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 03: cimport numpy as np
 04: # These imports have to be in the same cell as the function and must be prefaced
 05: # with %%cython
 06: 
 07: @cython.boundscheck(False)
 08: @cython.wraparound(False)
+09: def add2(double[:] x):
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9_1add2(PyObject *__pyx_self, PyObject *__pyx_arg_x); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9_1add2 = {"add2", (PyCFunction)__pyx_pw_46_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9_1add2, METH_O, 0};
static PyObject *__pyx_pw_46_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9_1add2(PyObject *__pyx_self, PyObject *__pyx_arg_x) {
  __Pyx_memviewslice __pyx_v_x = { 0, 0, { 0 }, { 0 }, { 0 } };
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("add2 (wrapper)", 0);
  assert(__pyx_arg_x); {
    __pyx_v_x = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_arg_x); if (unlikely(!__pyx_v_x.memview)) __PYX_ERR(0, 9, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9.add2", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_46_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9_add2(__pyx_self, __pyx_v_x);

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9_add2(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_x) {
  unsigned long __pyx_v_i;
  unsigned long __pyx_v_N;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("add2", 0);
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9.add2", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __PYX_XDEC_MEMVIEW(&__pyx_v_x, 1);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__20 = PyTuple_Pack(4, __pyx_n_s_x, __pyx_n_s_x, __pyx_n_s_i, __pyx_n_s_N); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__20);
  __Pyx_GIVEREF(__pyx_tuple__20);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_915716b2eeb0c1d6b095462fdf7bd7e9_1add2, NULL, __pyx_n_s_cython_magic_915716b2eeb0c1d6b0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_add2, __pyx_t_1) < 0) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__21 = (PyObject*)__Pyx_PyCode_New(1, 0, 4, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_kghose_ipython_cython__cy, __pyx_n_s_add2, 9, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__21)) __PYX_ERR(0, 9, __pyx_L1_error)
+10:     cdef unsigned long i, N = x.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_x, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_unsigned_long(__pyx_t_2); if (unlikely((__pyx_t_3 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_N = __pyx_t_3;
+11:     for i in range(N):
  __pyx_t_3 = __pyx_v_N;
  for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
    __pyx_v_i = __pyx_t_4;
+12:         x[i] += 1
    __pyx_t_5 = __pyx_v_i;
    *((double *) ( /* dim=0 */ (__pyx_v_x.data + __pyx_t_5 * __pyx_v_x.strides[0]) )) += 1.0;
  }

In [42]:
x = np.ones(100000)
%timeit add2(x)


57.9 µs ± 451 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [27]:
def af(x):
    x += 1
    return x

In [28]:
x = np.ones(100000)
%timeit af(x)


45.7 µs ± 760 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [ ]: