9.3.0 How to Build Cython Code
Contents
Estimated time for this notebook: 20 minutes
Cython can be viewed as an extension of Python where variables and functions are annotated with extra information, in particular types. The resulting Cython source code will be compiled into optimized C or C++ code, which can potentially speed up slow Python code. In other words, Cython provides a way of writing Python with comparable performance to that of C/C++.
9.3.0 How to Build Cython Code#
Cython code must, unlike Python, be compiled. This happens in the following stages:
The cython code in
.pyx
file will be translated to aC
file.The
C
file will be compiled by a C compiler into a shared library, which will be directly loaded into Python.
If you’re writing .py
files, you use the cythonize
command in your terminal.
In a Jupyter notebook, everything is a lot easier. One needs only to load the Cython extension (%load_ext Cython
) at the beginning and use %%cython
cell magic. Cells starting with %%cython
will be treated as a .pyx
code and, consequently, compiled.
For details, please see Building Cython Code.
9.3.1 Compiling a Pure Python Function#
We’ll copy our pure Python mandel()
function from the earlier notebook and redefine our real and imaginary inputs.
xmin = -1.5
ymin = -1.0
xmax = 0.5
ymax = 1.0
resolution = 300
xstep = (xmax - xmin) / resolution
ystep = (ymax - ymin) / resolution
xs = [(xmin + (xmax - xmin) * i / resolution) for i in range(resolution)]
ys = [(ymin + (ymax - ymin) * i / resolution) for i in range(resolution)]
def mandel(constant, max_iterations=50):
"""Computes the values of the series for up to a maximum number of iterations.
The function stops when the absolute value of the series surpasses 2 or when it reaches the maximum
number of iterations.
Returns the number of iterations.
"""
value = 0
counter = 0
while counter < max_iterations:
if abs(value) > 2:
break
value = (value * value) + constant
counter = counter + 1
return counter
assert mandel(0) == 50
assert mandel(3) == 1
assert mandel(0.5) == 5
We will cythonise our function without adding any type hints.
%load_ext Cython
%%cython
def mandel_cython():
value = 0
mandel_cython()
%%cython
def mandel_cython(constant, max_iterations=50):
"""Computes the values of the series for up to a maximum number of iterations.
The function stops when the absolute value of the series surpasses 2 or when it reaches the maximum
number of iterations.
Returns the number of iterations.
"""
value = 0
counter = 0
while counter < max_iterations:
if abs(value) > 2:
break
value = (value * value) + constant
counter = counter + 1
return counter
assert mandel_cython(0) == 50
assert mandel_cython(3) == 1
assert mandel_cython(0.5) == 5
Let’s verify the result
data_python = [[mandel(x + 1j * y) for x in xs] for y in ys]
data_cython = [[mandel_cython(x + 1j * y) for x in xs] for y in ys]
from matplotlib import pyplot as plt
plt.set_cmap("cividis") # use a CVD-friendly palette
f, axarr = plt.subplots(1, 2)
axarr[0].imshow(data_python, interpolation="none", extent=[xmin, xmax, ymin, ymax])
axarr[0].set_title("Pure Python")
axarr[0].set_ylabel("Imaginary")
axarr[0].set_xlabel("Real")
axarr[1].imshow(data_cython, interpolation="none", extent=[xmin, xmax, ymin, ymax])
axarr[1].set_title("Cython")
axarr[1].set_ylabel("Imaginary")
axarr[1].set_xlabel("Real")
f.tight_layout()
<Figure size 640x480 with 0 Axes>
%%timeit
[[mandel(x + 1j * y) for x in xs] for y in ys] # pure python
386 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
[[mandel_cython(x + 1j * y) for x in xs] for y in ys] # cython
270 ms ± 1.98 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
We have improved the performance of a factor of 1.5 by just using the Cython compiler, without changing the code!
9.3.2 Cython with C Types#
But we can do better by telling Cython what C data types we would use in the code. Note we’re not actually writing C, we’re writing Python with C types.
The –annotate Option#
If we pass the --annotate
/-a
option to %%cython
then it will output information about the line-by-line cost of running your function. You can use this to target the most costly operations first or to estimate how much more optimising there is to do.
%%cython --annotate
def mandel_cython(constant, max_iterations=50):
"""Computes the values of the series for up to a maximum number of iterations.
The function stops when the absolute value of the series surpasses 2 or when it reaches the maximum
number of iterations.
Returns the number of iterations.
"""
value = 0
counter = 0
while counter < max_iterations:
if abs(value) > 2:
break
value = (value * value) + constant
counter = counter + 1
return counter
Generated by Cython 0.29.37
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:
+02: def mandel_cython(constant, max_iterations=50):
/* Python wrapper */ static PyObject *__pyx_pw_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_1mandel_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_mandel_cython[] = "Computes the values of the series for up to a maximum number of iterations. \n \n The function stops when the absolute value of the series surpasses 2 or when it reaches the maximum \n number of iterations.\n \n Returns the number of iterations.\n "; static PyMethodDef __pyx_mdef_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_1mandel_cython = {"mandel_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_1mandel_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_mandel_cython}; static PyObject *__pyx_pw_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_1mandel_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_v_constant = 0; PyObject *__pyx_v_max_iterations = 0; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("mandel_cython (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_constant,&__pyx_n_s_max_iterations,0}; PyObject* values[2] = {0,0}; values[1] = ((PyObject *)__pyx_int_50); 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); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_constant)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; CYTHON_FALLTHROUGH; case 1: if (kw_args > 0) { PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_max_iterations); if (value) { values[1] = value; kw_args--; } } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "mandel_cython") < 0)) __PYX_ERR(0, 2, __pyx_L3_error) } } else { switch (PyTuple_GET_SIZE(__pyx_args)) { case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); break; default: goto __pyx_L5_argtuple_error; } } __pyx_v_constant = values[0]; __pyx_v_max_iterations = values[1]; } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("mandel_cython", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab.mandel_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_mandel_cython(__pyx_self, __pyx_v_constant, __pyx_v_max_iterations); int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_mandel_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_constant, PyObject *__pyx_v_max_iterations) { PyObject *__pyx_v_value = NULL; PyObject *__pyx_v_counter = NULL; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("mandel_cython", 0); /* … */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_3); __Pyx_AddTraceback("_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab.mandel_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XDECREF(__pyx_v_value); __Pyx_XDECREF(__pyx_v_counter); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* … */ __pyx_tuple_ = PyTuple_Pack(4, __pyx_n_s_constant, __pyx_n_s_max_iterations, __pyx_n_s_value, __pyx_n_s_counter); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 2, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); /* … */ __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_ec7ea0ae77b0beda7a24ea5675dd13ab_1mandel_cython, NULL, __pyx_n_s_cython_magic_ec7ea0ae77b0beda7a); 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_mandel_cython, __pyx_t_1) < 0) __PYX_ERR(0, 2, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
03: """Computes the values of the series for up to a maximum number of iterations.
04:
05: The function stops when the absolute value of the series surpasses 2 or when it reaches the maximum
06: number of iterations.
07:
08: Returns the number of iterations.
09: """
10:
+11: value = 0
__Pyx_INCREF(__pyx_int_0);
__pyx_v_value = __pyx_int_0;
12:
+13: counter = 0
__Pyx_INCREF(__pyx_int_0);
__pyx_v_counter = __pyx_int_0;
+14: while counter < max_iterations:
while (1) { __pyx_t_1 = PyObject_RichCompare(__pyx_v_counter, __pyx_v_max_iterations, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error) __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 14, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; if (!__pyx_t_2) break;
+15: if abs(value) > 2:
__pyx_t_1 = __Pyx_PyNumber_Absolute(__pyx_v_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_int_2, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 15, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 15, __pyx_L1_error) __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (__pyx_t_2) { /* … */ }
+16: break
goto __pyx_L4_break;
17:
+18: value = (value * value) + constant
__pyx_t_3 = PyNumber_Multiply(__pyx_v_value, __pyx_v_value); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_1 = PyNumber_Add(__pyx_t_3, __pyx_v_constant); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 18, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; __Pyx_DECREF_SET(__pyx_v_value, __pyx_t_1); __pyx_t_1 = 0;
19:
+20: counter = counter + 1
__pyx_t_1 = __Pyx_PyInt_AddObjC(__pyx_v_counter, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 20, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF_SET(__pyx_v_counter, __pyx_t_1); __pyx_t_1 = 0; } __pyx_L4_break:;
21:
+22: return counter
__Pyx_XDECREF(__pyx_r); __Pyx_INCREF(__pyx_v_counter); __pyx_r = __pyx_v_counter; goto __pyx_L0;
Typing Variables#
%%cython
def mandel_cython_var_typed(constant, max_iterations=50):
"""Computes the values of the series for up to a maximum number of iterations.
The function stops when the absolute value of the series surpasses 2 or when it reaches the maximum
number of iterations.
Returns the number of iterations.
"""
cdef double complex value # typed variable
value = 0
counter = 0
while counter < max_iterations:
if abs(value) > 2:
break
value = (value * value) + constant
counter = counter + 1
return counter
assert mandel_cython_var_typed(0) == 50
assert mandel_cython_var_typed(3) == 1
assert mandel_cython_var_typed(0.5) == 5
%%timeit
[[mandel_cython_var_typed(x + 1j * y) for x in xs] for y in ys]
169 ms ± 645 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Typing Function Parameters and Return Values#
%%cython
cpdef int mandel_cython_func_typed(double complex constant, int max_iterations=50):
"""Computes the values of the series for up to a maximum number of iterations.
The function stops when the absolute value of the series surpasses 2 or when it reaches the maximum
number of iterations.
Returns the number of iterations.
"""
cdef double complex value # typed variable
value = 0
cdef int counter = 0
while counter < max_iterations:
if abs(value) > 2:
break
value = (value * value) + constant
counter = counter + 1
return counter
assert mandel_cython_func_typed(0) == 50
assert mandel_cython_func_typed(3) == 1
assert mandel_cython_func_typed(0.5) == 5
%%timeit
[[mandel_cython_func_typed(x + 1j * y) for x in xs] for y in ys]
37.7 ms ± 114 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Cython with numpy ndarray#
You can use NumPy from Cython exactly the same as in regular Python, but by doing so you are losing potentially high speedups because Cython has support for fast access to NumPy arrays.
import numpy as np
cs_listcomp = [[(x + 1j * y) for x in xs] for y in ys]
cs = np.asarray(cs_listcomp)
%%cython
import numpy as np
cimport numpy as np
cpdef int mandel_cython_numpy(np.ndarray[double complex, ndim=2] constants, int max_iterations=50):
cdef np.ndarray[long,ndim=2] diverged_at_count
cdef np.ndarray[double complex, ndim=2] value
cdef int counter
diverged_at_count = np.ones((constants.shape[0], constants.shape[1]), dtype=int)*max_iterations
value = np.zeros((constants.shape[0], constants.shape[1]), dtype=complex)
counter = 0
while counter < max_iterations:
value = value*value + constants
diverging = abs(value) > 2
# Any positions which are:
# - diverging
# - haven't diverged before
# are diverging for the first time
first_diverged_this_time = np.logical_and(
diverging,
diverged_at_count == max_iterations
)
# Update diverged_at_count for all positions which first diverged at this step
diverged_at_count[first_diverged_this_time] = counter
# Reset any divergent values to exactly 2
value[diverging] = 2
counter = counter + 1
return diverged_at_count
assert mandel_cython_numpy(np.asarray([[0 + 1j*0]])) == np.asarray([[50]])
assert mandel_cython_numpy(np.asarray([[4 + 1j*0]])) == np.asarray([[0]])
Note the double import of numpy:
the standard numpy module
the Cython-enabled version of numpy that ensures fast indexing of and other operations on arrays.
Both import statements are necessary in code that uses numpy arrays. The new thing in the code above is declaration of arrays by np.ndarray.
%%timeit
mandel_cython_numpy(cs)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: only size-1 arrays can be converted to Python scalars
Exception ignored in: '_cython_magic_33a5a6295202ea804fc70605b98fa460.mandel_cython_numpy'
Traceback (most recent call last):
File "<magic-timeit>", line 1, in inner
TypeError: only size-1 arrays can be converted to Python scalars
58.1 ms ± 150 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)