Cython¶

https://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html

Fibonacci numbers¶

In [4]:
def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a+b
    return a
In [12]:
%time fib(10_000)
CPU times: total: 15.6 ms
Wall time: 999 μs
Out[12]:
33644764876431783266621612005107543310302148460680063906564769974680081442166662368155595513633734025582065332680836159373734790483865268263040892463056431887354544369559827491606602099884183933864652731300088830269235673613135117579297437854413752130520504347701602264758318906527890855154366159582987279682987510631200575428783453215515103870818298969791613127856265033195487140214287532698187962046936097879900350962302291026368131493195275630227837628441540360584402572114334961180023091208287046088923962328835461505776583271252546093591128203925285393434620904245248929403901706233888991085841065183173360437470737908552631764325733993712871937587746897479926305837065742830161637408969178426378624212835258112820516370298089332099905707920064367426202389783111470054074998459250360633560933883831923386783056136435351892133279732908133732642652633989763922723407882928177953580570993691049175470808931841056146322338217465637321248226383092103297701648054726243842374862411453093812206564914032751086643394517512161526545361333111314042436854805106765843493523836959653428071768775328348234345557366719731392746273629108210679280784718035329131176778924659089938635459327894523777674406192240337638674004021330343297496902028328145933418826817683893072003634795623117103101291953169794607632737589253530772552375943788434504067715555779056450443016640119462580972216729758615026968443146952034614932291105970676243268515992834709891284706740862008587135016260312071903172086094081298321581077282076353186624611278245537208532365305775956430072517744315051539600905168603220349163222640885248852433158051534849622434848299380905070483482449327453732624567755879089187190803662058009594743150052402532709746995318770724376825907419939632265984147498193609285223945039707165443156421328157688908058783183404917434556270520223564846495196112460268313970975069382648706613264507665074611512677522748621598642530711298441182622661057163515069260029861704945425047491378115154139941550671256271197133252763631939606902895650288268608362241082050562430701794976171121233066073310059947366875
In [13]:
%time fib(100_000)
CPU times: total: 93.8 ms
Wall time: 90.4 ms
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\site-packages\IPython\core\formatters.py:770, in PlainTextFormatter.__call__(self, obj)
    763 stream = StringIO()
    764 printer = pretty.RepresentationPrinter(stream, self.verbose,
    765     self.max_width, self.newline,
    766     max_seq_length=self.max_seq_length,
    767     singleton_pprinters=self.singleton_printers,
    768     type_pprinters=self.type_printers,
    769     deferred_pprinters=self.deferred_printers)
--> 770 printer.pretty(obj)
    771 printer.flush()
    772 return stream.getvalue()

File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\site-packages\IPython\lib\pretty.py:394, in RepresentationPrinter.pretty(self, obj)
    391 for cls in _get_mro(obj_class):
    392     if cls in self.type_pprinters:
    393         # printer registered in self.type_pprinters
--> 394         return self.type_pprinters[cls](obj, self, cycle)
    395     else:
    396         # deferred printer
    397         printer = self._in_deferred_types(cls)

File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\Lib\site-packages\IPython\lib\pretty.py:794, in _repr_pprint(obj, p, cycle)
    792 """A pprint that just redirects to the normal repr function."""
    793 # Find newlines and replace them with p.break_()
--> 794 output = repr(obj)
    795 lines = output.splitlines()
    796 with p.group():

ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
In [5]:
import sys
In [6]:
sys.set_int_max_str_digits(10**6) #set the limit for string representation of INTEGER
In [19]:
%time print(len(str(fib(1_000_000))))
208988
CPU times: total: 6.98 s
Wall time: 7 s
In [20]:
!pip install cython
Defaulting to user installation because normal site-packages is not writeable
Collecting cython
  Downloading cython-3.2.4-cp311-cp311-win_amd64.whl.metadata (7.7 kB)
Downloading cython-3.2.4-cp311-cp311-win_amd64.whl (2.8 MB)
   ---------------------------------------- 0.0/2.8 MB ? eta -:--:--
   ---------------------------------------- 0.0/2.8 MB ? eta -:--:--
   ---------------------------------------- 0.0/2.8 MB 325.1 kB/s eta 0:00:09
   -- ------------------------------------- 0.2/2.8 MB 1.3 MB/s eta 0:00:02
   ------- -------------------------------- 0.5/2.8 MB 3.3 MB/s eta 0:00:01
   --------------- ------------------------ 1.1/2.8 MB 5.1 MB/s eta 0:00:01
   ------------------------ --------------- 1.7/2.8 MB 6.8 MB/s eta 0:00:01
   ------------------------------------ --- 2.6/2.8 MB 8.6 MB/s eta 0:00:01
   ---------------------------------------  2.8/2.8 MB 9.3 MB/s eta 0:00:01
   ---------------------------------------- 2.8/2.8 MB 7.7 MB/s eta 0:00:00
Installing collected packages: cython
Successfully installed cython-3.2.4
  WARNING: The scripts cygdb.exe, cython.exe and cythonize.exe are installed in 'C:\Users\student\AppData\Roaming\Python\Python311\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
In [1]:
%load_ext cython
In [3]:
%%cython -a

def fib_cython(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a+b
    return a
Content of stdout:
_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9.c
   Creating library C:\Users\student\.ipython\cython\Users\student\.ipython\cython\_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9.cp311-win_amd64.lib and object C:\Users\student\.ipython\cython\Users\student\.ipython\cython\_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9.cp311-win_amd64.exp
Generating code
Finished generating code
Out[3]:

Generated by Cython 3.2.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.

 1: 
+2: def fib_cython(n):
/* Python wrapper */
static PyObject *__pyx_pw_78_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9_1fib_cython(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
static PyMethodDef __pyx_mdef_78_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9_1fib_cython = {"fib_cython", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_78_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9_1fib_cython, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_78_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9_1fib_cython(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_n = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fib_cython (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_n,0};
  PyObject* values[1] = {0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 2, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "fib_cython", 0) < (0)) __PYX_ERR(0, 2, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 1; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("fib_cython", 1, 1, 1, i); __PYX_ERR(0, 2, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 1)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2, __pyx_L3_error)
    }
    __pyx_v_n = values[0];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("fib_cython", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 2, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9.fib_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_78_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9_fib_cython(__pyx_self, __pyx_v_n);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_78_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9_fib_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_n) {
  PyObject *__pyx_v_a = NULL;
  PyObject *__pyx_v_b = NULL;
  CYTHON_UNUSED PyObject *__pyx_v__ = NULL;
  PyObject *__pyx_r = NULL;
/* … */
  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_78_cython_magic_0f4cc6ebbb2485effa031413a08c5a20df5d5af666fda0a2c0be23e925ed81e9_1fib_cython, 0, __pyx_mstate_global->__pyx_n_u_fib_cython, NULL, __pyx_mstate_global->__pyx_n_u_cython_magic_0f4cc6ebbb2485effa, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[0])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2);
  #endif
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_fib_cython, __pyx_t_2) < (0)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_test, __pyx_t_2) < (0)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+3:     a, b = 0, 1
  __pyx_t_1 = __pyx_mstate_global->__pyx_int_0;
  __Pyx_INCREF(__pyx_t_1);
  __pyx_t_2 = __pyx_mstate_global->__pyx_int_1;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_v_a = __pyx_t_1;
  __pyx_t_1 = 0;
  __pyx_v_b = __pyx_t_2;
  __pyx_t_2 = 0;
+4:     for _ in range(n):
  __pyx_t_1 = NULL;
  __pyx_t_3 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_v_n};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)(&PyRange_Type), __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    {
      __pyx_t_2 = __pyx_t_4(__pyx_t_1);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 4, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v__, __pyx_t_2);
    __pyx_t_2 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+5:         a, b = b, a+b
    __pyx_t_2 = __pyx_v_b;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_5 = PyNumber_Add(__pyx_v_a, __pyx_v_b); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 5, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF_SET(__pyx_v_a, __pyx_t_2);
    __pyx_t_2 = 0;
    __Pyx_DECREF_SET(__pyx_v_b, __pyx_t_5);
    __pyx_t_5 = 0;
+6:     return a
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_a);
  __pyx_r = __pyx_v_a;
  goto __pyx_L0;
In [7]:
%time print(len(str(fib_cython(1_000_000))))
208988
CPU times: total: 7.09 s
Wall time: 7.09 s

Primes¶

In [9]:
import cython

def primes(nb_primes: cython.int):
    i: cython.int
    p: cython.int[10000]

    if nb_primes > 10000:
        nb_primes = 10000

    if not cython.compiled:  # Only if regular Python is running
        print('NOT COMPILED')
        p = [0] * 10000       # Make p work almost like a C array

    len_p: cython.int = 0  # The current number of elements in p.
    n: cython.int = 2
    while len_p < nb_primes:
        # Is n prime?
        for i in p[:len_p]:
            if n % i == 0:
                break

        # If no break occurred in the loop, we have a prime.
        else:
            p[len_p] = n
            len_p += 1
        n += 1

    # Let's copy the result into a Python list:
    result_as_list = [prime for prime in p[:len_p]]
    return result_as_list
In [11]:
print(*primes(100))
NOT COMPILED
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541
In [12]:
%time primes(10000)[-10:]
NOT COMPILED
CPU times: total: 3.41 s
Wall time: 3.39 s
Out[12]:
[104677,
 104681,
 104683,
 104693,
 104701,
 104707,
 104711,
 104717,
 104723,
 104729]
In [13]:
%%cython -a

import cython

def primes_cython(nb_primes: cython.int):
    i: cython.int
    p: cython.int[10000]

    if nb_primes > 10000:
        nb_primes = 10000

    if not cython.compiled:  # Only if regular Python is running
        print('NOT COMPILED')
        p = [0] * 10000       # Make p work almost like a C array

    len_p: cython.int = 0  # The current number of elements in p.
    n: cython.int = 2
    while len_p < nb_primes:
        # Is n prime?
        for i in p[:len_p]:
            if n % i == 0:
                break

        # If no break occurred in the loop, we have a prime.
        else:
            p[len_p] = n
            len_p += 1
        n += 1

    # Let's copy the result into a Python list:
    result_as_list = [prime for prime in p[:len_p]]
    return result_as_list
Content of stdout:
_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a.c
   Creating library C:\Users\student\.ipython\cython\Users\student\.ipython\cython\_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a.cp311-win_amd64.lib and object C:\Users\student\.ipython\cython\Users\student\.ipython\cython\_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a.cp311-win_amd64.exp
Generating code
Finished generating code
Out[13]:

Generated by Cython 3.2.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: 
+02: import cython
  __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_test, __pyx_t_3) < (0)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 03: 
+04: def primes_cython(nb_primes: cython.int):
/* Python wrapper */
static PyObject *__pyx_pw_78_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a_1primes_cython(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
static PyMethodDef __pyx_mdef_78_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a_1primes_cython = {"primes_cython", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_78_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a_1primes_cython, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_78_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a_1primes_cython(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  int __pyx_v_nb_primes;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("primes_cython (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_nb_primes,0};
  PyObject* values[1] = {0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 4, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "primes_cython", 0) < (0)) __PYX_ERR(0, 4, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 1; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("primes_cython", 1, 1, 1, i); __PYX_ERR(0, 4, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 1)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4, __pyx_L3_error)
    }
    __pyx_v_nb_primes = __Pyx_PyLong_As_int(values[0]); if (unlikely((__pyx_v_nb_primes == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4, __pyx_L3_error)
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("primes_cython", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 4, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a.primes_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_78_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a_primes_cython(__pyx_self, __pyx_v_nb_primes);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_78_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a_primes_cython(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_nb_primes) {
  int __pyx_v_i;
  int __pyx_v_p[10000];
  int __pyx_v_len_p;
  int __pyx_v_n;
  PyObject *__pyx_v_result_as_list = NULL;
  int __pyx_7genexpr__pyx_v_prime;
  PyObject *__pyx_r = NULL;
/* … */
  __pyx_t_2 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_nb_primes, __pyx_mstate_global->__pyx_kp_u_cython_int) < (0)) __PYX_ERR(0, 4, __pyx_L1_error)
  __pyx_t_3 = __Pyx_CyFunction_New(&__pyx_mdef_78_cython_magic_1b7829d702aa5b00267382ad93315eefde3d25e18d2b69d27c4b320c3d1da98a_1primes_cython, 0, __pyx_mstate_global->__pyx_n_u_primes_cython, NULL, __pyx_mstate_global->__pyx_n_u_cython_magic_1b7829d702aa5b0026, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[0])); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_3);
  #endif
  __Pyx_CyFunction_SetAnnotationsDict(__pyx_t_3, __pyx_t_2);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_primes_cython, __pyx_t_3) < (0)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 05:     i: cython.int
 06:     p: cython.int[10000]
 07: 
+08:     if nb_primes > 10000:
  __pyx_t_1 = (__pyx_v_nb_primes > 0x2710);
  if (__pyx_t_1) {
/* … */
  }
+09:         nb_primes = 10000
    __pyx_v_nb_primes = 0x2710;
 10: 
 11:     if not cython.compiled:  # Only if regular Python is running
 12:         print('NOT COMPILED')
 13:         p = [0] * 10000       # Make p work almost like a C array
 14: 
+15:     len_p: cython.int = 0  # The current number of elements in p.
  __pyx_v_len_p = 0;
+16:     n: cython.int = 2
  __pyx_v_n = 2;
+17:     while len_p < nb_primes:
  while (1) {
    __pyx_t_1 = (__pyx_v_len_p < __pyx_v_nb_primes);
    if (!__pyx_t_1) break;
 18:         # Is n prime?
+19:         for i in p[:len_p]:
    __pyx_t_3 = (__pyx_v_p + __pyx_v_len_p);
    for (__pyx_t_4 = __pyx_v_p; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) {
      __pyx_t_2 = __pyx_t_4;
      __pyx_v_i = (__pyx_t_2[0]);
+20:             if n % i == 0:
      if (unlikely(__pyx_v_i == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
        __PYX_ERR(0, 20, __pyx_L1_error)
      }
      __pyx_t_1 = (__Pyx_mod_int(__pyx_v_n, __pyx_v_i, 0) == 0);
      if (__pyx_t_1) {
/* … */
      }
    }
    /*else*/ {
+21:                 break
        goto __pyx_L7_break;
 22: 
 23:         # If no break occurred in the loop, we have a prime.
 24:         else:
+25:             p[len_p] = n
      (__pyx_v_p[__pyx_v_len_p]) = __pyx_v_n;
+26:             len_p += 1
      __pyx_v_len_p = (__pyx_v_len_p + 1);
    }
    __pyx_L7_break:;
+27:         n += 1
    __pyx_v_n = (__pyx_v_n + 1);
  }
 28: 
 29:     # Let's copy the result into a Python list:
+30:     result_as_list = [prime for prime in p[:len_p]]
  { /* enter inner scope */
    __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 30, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_3 = (__pyx_v_p + __pyx_v_len_p);
    for (__pyx_t_4 = __pyx_v_p; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) {
      __pyx_t_2 = __pyx_t_4;
      __pyx_7genexpr__pyx_v_prime = (__pyx_t_2[0]);
      __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_7genexpr__pyx_v_prime); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 30, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_5, (PyObject*)__pyx_t_6))) __PYX_ERR(0, 30, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    }
  } /* exit inner scope */
  __pyx_v_result_as_list = ((PyObject*)__pyx_t_5);
  __pyx_t_5 = 0;
+31:     return result_as_list
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_result_as_list);
  __pyx_r = __pyx_v_result_as_list;
  goto __pyx_L0;
In [14]:
%time primes_cython(10000)[-10:]
CPU times: total: 156 ms
Wall time: 136 ms
Out[14]:
[104677,
 104681,
 104683,
 104693,
 104701,
 104707,
 104711,
 104717,
 104723,
 104729]
NOT COMPILED
CPU times: total: 3.41 s

COMPILED:
CPU times: total: 156 ms

Numba¶

https://numba.pydata.org/

Mandelbrot set (fractal)¶

https://en.wikipedia.org/wiki/Mandelbrot_set

In [16]:
import numpy as np

from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [15, 5]
plt.rcParams['figure.dpi'] = 100

from numba import jit, vectorize, guvectorize, float64, complex64, int32, float32

def mandelbrot_set(xmin,xmax,ymin,ymax,width,height,maxiter, mandelbrot_func, real=False):
    r1 = np.linspace(xmin, xmax, width)
    r2 = np.linspace(ymin, ymax, height)
    if real:
        return [[mandelbrot_func(r, i, maxiter) for r in r1] for i in r2]
    return [[mandelbrot_func(complex(r, i), maxiter) for r in r1] for i in r2]

male_hodnoty = (-2.0,0.5,-1.25,1.25,1000,1000,80)
velke_hodnoty = (-0.74877,-0.74872,0.06505,0.06510,1000,1000,2048)
    
def pds_zobraz(f, real=False):
    %time plt.subplot(1, 2, 1).imshow(mandelbrot_set(*male_hodnoty, f, real))
    %time plt.subplot(1, 2, 2).imshow(mandelbrot_set(*velke_hodnoty, f, real))    
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[16], line 8
      5 plt.rcParams['figure.figsize'] = [15, 5]
      6 plt.rcParams['figure.dpi'] = 100
----> 8 from numba import jit, vectorize, guvectorize, float64, complex64, int32, float32
     10 def mandelbrot_set(xmin,xmax,ymin,ymax,width,height,maxiter, mandelbrot_func, real=False):
     11     r1 = np.linspace(xmin, xmax, width)

ModuleNotFoundError: No module named 'numba'
In [17]:
!pip install numba
Defaulting to user installation because normal site-packages is not writeable
Collecting numba
  Downloading numba-0.64.0-cp311-cp311-win_amd64.whl.metadata (2.8 kB)
Collecting llvmlite<0.47,>=0.46.0dev0 (from numba)
  Downloading llvmlite-0.46.0-cp311-cp311-win_amd64.whl.metadata (4.9 kB)
Requirement already satisfied: numpy<2.5,>=1.22 in c:\program files\arcgis\pro\bin\python\envs\arcgispro-py3\lib\site-packages (from numba) (1.26.4)
Downloading numba-0.64.0-cp311-cp311-win_amd64.whl (2.7 MB)
   ---------------------------------------- 0.0/2.7 MB ? eta -:--:--
   ---------------------------------------- 0.0/2.7 MB ? eta -:--:--
    --------------------------------------- 0.1/2.7 MB 1.1 MB/s eta 0:00:03
   ------ --------------------------------- 0.5/2.7 MB 4.8 MB/s eta 0:00:01
   --------------- ------------------------ 1.0/2.7 MB 7.3 MB/s eta 0:00:01
   -------------------------- ------------- 1.8/2.7 MB 9.6 MB/s eta 0:00:01
   ---------------------------------------  2.7/2.7 MB 11.6 MB/s eta 0:00:01
   ---------------------------------------- 2.7/2.7 MB 11.7 MB/s eta 0:00:00
Downloading llvmlite-0.46.0-cp311-cp311-win_amd64.whl (38.1 MB)
   ---------------------------------------- 0.0/38.1 MB ? eta -:--:--
   - -------------------------------------- 1.6/38.1 MB 33.1 MB/s eta 0:00:02
   --- ------------------------------------ 3.5/38.1 MB 36.9 MB/s eta 0:00:01
   ------ --------------------------------- 5.9/38.1 MB 41.7 MB/s eta 0:00:01
   --------- ------------------------------ 9.1/38.1 MB 48.7 MB/s eta 0:00:01
   -------------- ------------------------- 13.5/38.1 MB 73.1 MB/s eta 0:00:01
   ------------------- -------------------- 18.9/38.1 MB 108.8 MB/s eta 0:00:01
   ------------------------- -------------- 24.3/38.1 MB 131.2 MB/s eta 0:00:01
   ------------------------------- -------- 29.9/38.1 MB 131.2 MB/s eta 0:00:01
   ------------------------------------- -- 35.4/38.1 MB 131.2 MB/s eta 0:00:01
   ---------------------------------------  38.1/38.1 MB 108.8 MB/s eta 0:00:01
   ---------------------------------------  38.1/38.1 MB 108.8 MB/s eta 0:00:01
   ---------------------------------------- 38.1/38.1 MB 54.4 MB/s eta 0:00:00
Installing collected packages: llvmlite, numba
Successfully installed llvmlite-0.46.0 numba-0.64.0
In [20]:
import numpy as np

from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [15, 5]
plt.rcParams['figure.dpi'] = 100

from numba import jit, vectorize, guvectorize, float64, complex64, int32, float32

def mandelbrot_set(xmin,xmax,ymin,ymax,width,height,maxiter, mandelbrot_func, real=False):
    r1 = np.linspace(xmin, xmax, width)
    r2 = np.linspace(ymin, ymax, height)
    if real:
        return [[mandelbrot_func(r, i, maxiter) for r in r1] for i in r2]
    return [[mandelbrot_func(complex(r, i), maxiter) for r in r1] for i in r2]

male_hodnoty = (-2.0,0.5,-1.25,1.25,1000,1000,80)
velke_hodnoty = (-0.74877,-0.74872,0.06505,0.06510,1000,1000,2048)
    
def pds_zobraz(f, real=False):
    %time plt.subplot(1, 2, 1).imshow(mandelbrot_set(*male_hodnoty, f, real))
    %time plt.subplot(1, 2, 2).imshow(mandelbrot_set(*velke_hodnoty, f, real))    
In [21]:
def mandelbrot_python(z, maxiter):
    c = z
    for n in range(maxiter):
        if abs(z) > 2:
            return n
        z = z*z + c
    return maxiter
In [22]:
pds_zobraz(mandelbrot_python)
CPU times: total: 3.5 s
Wall time: 3.53 s
CPU times: total: 1min 20s
Wall time: 1min 20s
No description has been provided for this image
In [23]:
%%cython -a

def mandelbrot_cython(z, maxiter):
    c = z
    for n in range(maxiter):
        if abs(z) > 2:
            return n
        z = z*z + c
    return maxiter
Content of stdout:
_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8.c
   Creating library C:\Users\student\.ipython\cython\Users\student\.ipython\cython\_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8.cp311-win_amd64.lib and object C:\Users\student\.ipython\cython\Users\student\.ipython\cython\_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8.cp311-win_amd64.exp
Generating code
Finished generating code
Out[23]:

Generated by Cython 3.2.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.

 1: 
+2: def mandelbrot_cython(z, maxiter):
/* Python wrapper */
static PyObject *__pyx_pw_78_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8_1mandelbrot_cython(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
static PyMethodDef __pyx_mdef_78_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8_1mandelbrot_cython = {"mandelbrot_cython", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_78_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8_1mandelbrot_cython, __Pyx_METH_FASTCALL|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_78_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8_1mandelbrot_cython(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_z = 0;
  PyObject *__pyx_v_maxiter = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("mandelbrot_cython (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_z,&__pyx_mstate_global->__pyx_n_u_maxiter,0};
  PyObject* values[2] = {0,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 2, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "mandelbrot_cython", 0) < (0)) __PYX_ERR(0, 2, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 2; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("mandelbrot_cython", 1, 2, 2, i); __PYX_ERR(0, 2, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 2)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2, __pyx_L3_error)
      values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2, __pyx_L3_error)
    }
    __pyx_v_z = values[0];
    __pyx_v_maxiter = values[1];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("mandelbrot_cython", 1, 2, 2, __pyx_nargs); __PYX_ERR(0, 2, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8.mandelbrot_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_78_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8_mandelbrot_cython(__pyx_self, __pyx_v_z, __pyx_v_maxiter);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_78_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8_mandelbrot_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_z, PyObject *__pyx_v_maxiter) {
  PyObject *__pyx_v_c = NULL;
  PyObject *__pyx_v_n = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_INCREF(__pyx_v_z);
/* … */
  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_78_cython_magic_b6c785402ae1d59614e18c678ca6495eceff68fd24223febae5bd8c8c6fe57f8_1mandelbrot_cython, 0, __pyx_mstate_global->__pyx_n_u_mandelbrot_cython, NULL, __pyx_mstate_global->__pyx_n_u_cython_magic_b6c785402ae1d59614, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[0])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2);
  #endif
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_mandelbrot_cython, __pyx_t_2) < (0)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_test, __pyx_t_2) < (0)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+3:     c = z
  __Pyx_INCREF(__pyx_v_z);
  __pyx_v_c = __pyx_v_z;
+4:     for n in range(maxiter):
  __pyx_t_2 = NULL;
  __pyx_t_3 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_maxiter};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(&PyRange_Type), __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    {
      __pyx_t_1 = __pyx_t_4(__pyx_t_2);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 4, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_n, __pyx_t_1);
    __pyx_t_1 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+5:         if abs(z) > 2:
    __pyx_t_1 = __Pyx_PyNumber_Absolute(__pyx_v_z); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_5 = PyObject_RichCompare(__pyx_t_1, __pyx_mstate_global->__pyx_int_2, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 5, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 5, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (__pyx_t_6) {
/* … */
    }
+6:             return n
      __Pyx_XDECREF(__pyx_r);
      __Pyx_INCREF(__pyx_v_n);
      __pyx_r = __pyx_v_n;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      goto __pyx_L0;
+7:         z = z*z + c
    __pyx_t_5 = PyNumber_Multiply(__pyx_v_z, __pyx_v_z); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 7, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_1 = PyNumber_Add(__pyx_t_5, __pyx_v_c); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF_SET(__pyx_v_z, __pyx_t_1);
    __pyx_t_1 = 0;
+8:     return maxiter
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_maxiter);
  __pyx_r = __pyx_v_maxiter;
  goto __pyx_L0;
In [24]:
pds_zobraz(mandelbrot_cython)
CPU times: total: 2.28 s
Wall time: 2.28 s
CPU times: total: 48.6 s
Wall time: 48.6 s
No description has been provided for this image
In [25]:
@jit
def mandelbrot_numba(z, maxiter):
    c = z
    for n in range(maxiter):
        if abs(z) > 2:
            return n
        z = z*z + c
    return maxiter
In [26]:
pds_zobraz(mandelbrot_numba) #Compiling at first run
CPU times: total: 1.3 s
Wall time: 3.73 s
CPU times: total: 3.52 s
Wall time: 3.51 s
No description has been provided for this image
In [27]:
pds_zobraz(mandelbrot_numba)
CPU times: total: 516 ms
Wall time: 532 ms
CPU times: total: 3.47 s
Wall time: 3.46 s
No description has been provided for this image

Do not compute square root (for the distance) ...¶

In [29]:
a = complex(3, 4)
In [30]:
abs(a)
Out[30]:
5.0
In [31]:
a.real, a.imag
Out[31]:
(3.0, 4.0)
In [32]:
import math

math.sqrt(a.real**2+a.imag**2)
Out[32]:
5.0
In [33]:
abs(a) > 2
Out[33]:
True
In [34]:
a.real**2+a.imag**2 > 4
Out[34]:
True
In [35]:
@jit
def mandelbrot_numba_sqr(z, maxiter):
    c = z
    for n in range(maxiter):
        if z.real**2+z.imag**2 > 4:
            return n
        z = z*z + c
    return maxiter
In [36]:
pds_zobraz(mandelbrot_numba_sqr)
CPU times: total: 625 ms
Wall time: 620 ms
CPU times: total: 2.19 s
Wall time: 2.18 s
No description has been provided for this image

$ z = \texttt{re}+i \cdot \texttt{im}$

$i^2 = -1$

$ z^2 = \left(\texttt{re}+i \cdot \texttt{im}\right)^2 = re^2+2 \cdot \texttt{re} \cdot \texttt{im} \cdot i + i^2 \cdot \texttt{im} = \texttt{re}^2+2 \cdot \texttt{re}\cdot \texttt{im} \cdot i - \texttt{im}$

In [37]:
@jit
def mandelbrot_numba_sqr_real(re, im, maxiter):
    c_re, c_im = re, im
    for n in range(maxiter):
        re2 = re**2
        im2 = im**2
        if re2+im2 > 4:
            return n
        # z = z*z+c
        re, im = re2-im2+c_re, 2*re*im+c_im
    return maxiter
In [39]:
pds_zobraz(mandelbrot_numba_sqr_real, real=True)
CPU times: total: 406 ms
Wall time: 411 ms
CPU times: total: 2.16 s
Wall time: 2.18 s
No description has been provided for this image
In [40]:
@jit(int32(complex64, int32))
def mandelbrot_types(c,maxiter):
    r = c.real
    i = c.imag
    for n in range(maxiter):
        r2 = r*r
        i2 = i*i
        if r2 + i2 > 4.0:
            return n
        i = 2*r*i+c.imag
        r = r2-i2+c.real
    return maxiter

@guvectorize([(complex64[:], int32, int32[:])], '(n),()->(n)', target='parallel')
def mandelbrot_numpy(c, maxiter, output):
    for i in range(c.shape[0]):
        output[i] = mandelbrot_types(c[i], maxiter)
        
def mandelbrot_set2(xmin,xmax,ymin,ymax,width,height,maxiter):
    r1 = np.linspace(xmin, xmax, width, dtype=np.float32)
    r2 = np.linspace(ymin, ymax, height, dtype=np.float32)
    c = r1 + r2[:,None]*1j    
    return mandelbrot_numpy(c,maxiter)
    
%time plt.subplot(1, 2, 1).imshow(mandelbrot_set2(*male_hodnoty))
%time plt.subplot(1, 2, 2).imshow(mandelbrot_set2(*velke_hodnoty))
CPU times: total: 156 ms
Wall time: 22 ms
CPU times: total: 1.91 s
Wall time: 179 ms
Out[40]:
<matplotlib.image.AxesImage at 0x20b79980950>
No description has been provided for this image
In [41]:
%%time
import numpy as np
from numba import cuda
from numba import *

from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [15, 5]
plt.rcParams['figure.dpi'] = 100

@jit
def mandel(real, imag, max_iters):
    cr = real
    ci = imag
    for n in range(max_iters):
        real2 = real*real
        imag2 = imag*imag
        if real2 + imag2 > 4.0:
            return n
        imag = 2*real*imag+ci
        real = real2-imag2+cr
    return max_iters

mandel_gpu = cuda.jit(uint32(float32, float32, uint32), device=True)(mandel)

@cuda.jit((float32, float32, float32, float32, uint32[:,:], uint32))
def mandel_kernel(min_x, max_x, min_y, max_y, image, iters):
  height = image.shape[0]
  width = image.shape[1]

  pixel_size_x = (max_x - min_x) / width
  pixel_size_y = (max_y - min_y) / height

  startX, startY = cuda.grid(2)
  gridX = cuda.gridDim.x * cuda.blockDim.x;
  gridY = cuda.gridDim.y * cuda.blockDim.y;

  for x in range(startX, width, gridX):
    real = min_x + x * pixel_size_x
    for y in range(startY, height, gridY):
      imag = min_y + y * pixel_size_y 
      image[y][x] = mandel_gpu(real, imag, iters)
        
gimage = np.zeros((1000, 1000), dtype = np.uint32)
blockdim = (32, 8)
griddim = (32,16)

d_image = cuda.to_device(gimage)
mandel_kernel[griddim, blockdim](-2.0, 1.0, -1.0, 1.0, d_image, 20) 
d_image.copy_to_host(gimage)
plt.subplot(1, 2, 1).imshow(gimage)

d_image = cuda.to_device(gimage)
mandel_kernel[griddim, blockdim](-0.74877,-0.74872,0.06505,0.06510, d_image, 2048) 
d_image.copy_to_host(gimage)
plt.subplot(1, 2, 2).imshow(gimage)
---------------------------------------------------------------------------
CudaSupportError                          Traceback (most recent call last)
File <timed exec>:23

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\decorators.py:133, in jit.<locals>._jit(func)
    131     from numba.core import typeinfer
    132     with typeinfer.register_dispatcher(disp):
--> 133         disp.compile_device(argtypes, restype)
    134 else:
    135     disp.compile(argtypes)

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\dispatcher.py:882, in CUDADispatcher.compile_device(self, args, return_type)
    875 fastmath = self.targetoptions.get('fastmath')
    877 nvvm_options = {
    878     'opt': 3 if self.targetoptions.get('opt') else 0,
    879     'fastmath': fastmath
    880 }
--> 882 cc = get_current_device().compute_capability
    883 cres = compile_cuda(self.py_func, return_type, args,
    884                     debug=debug,
    885                     lineinfo=lineinfo,
   (...)
    888                     nvvm_options=nvvm_options,
    889                     cc=cc)
    890 self.overloads[args] = cres

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\api.py:443, in get_current_device()
    441 def get_current_device():
    442     "Get current device associated with the current thread"
--> 443     return current_context().device

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\cudadrv\devices.py:220, in get_context(devnum)
    216 def get_context(devnum=None):
    217     """Get the current device or use a device by device number, and
    218     return the CUDA context.
    219     """
--> 220     return _runtime.get_or_create_context(devnum)

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\cudadrv\devices.py:138, in _Runtime.get_or_create_context(self, devnum)
    136 attached_ctx = self._get_attached_context()
    137 if attached_ctx is None:
--> 138     return self._get_or_create_context_uncached(devnum)
    139 else:
    140     return attached_ctx

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\cudadrv\devices.py:153, in _Runtime._get_or_create_context_uncached(self, devnum)
    147 """See also ``get_or_create_context(devnum)``.
    148 This version does not read the cache.
    149 """
    150 with self._lock:
    151     # Try to get the active context in the CUDA stack or
    152     # activate GPU-0 with the primary context
--> 153     with driver.get_active_context() as ac:
    154         if not ac:
    155             return self._activate_context_for(0)

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\cudadrv\driver.py:499, in _ActiveContext.__enter__(self)
    497 else:
    498     hctx = drvapi.cu_context(0)
--> 499     driver.cuCtxGetCurrent(byref(hctx))
    500     hctx = hctx if hctx.value else None
    502 if hctx is None:

File ~\AppData\Roaming\Python\Python311\site-packages\numba\cuda\cudadrv\driver.py:295, in Driver.__getattr__(self, fname)
    292 self.ensure_initialized()
    294 if self.initialization_error is not None:
--> 295     raise CudaSupportError("Error at driver init: \n%s:" %
    296                            self.initialization_error)
    298 if USE_NV_BINDING:
    299     return self._cuda_python_wrap_fn(fname)

CudaSupportError: Error at driver init: 

CUDA driver library cannot be found.
If you are sure that a CUDA driver is installed,
try setting environment variable NUMBA_CUDA_DRIVER
with the file path of the CUDA driver shared library.
:
In [ ]: