I am working on speeding up some Python/Numpy code with Cython, and am a bit unclear on the effects of "locally" setting (as defined here in the docs) compiler directives. In my case I'd like to use:
@cython.wraparound (False) #turn off negative indexing
@cython.boundscheck(False) #turn off bounds-checking
I understand that I can globally define this in my setup.py
file, but I'm developing for non-Cython users and would like the directives to be obvious from the .pyx
file.
If I am writing a .pyx
file with several functions defined in it, need I only set these once, or will they only apply to the next function defined? The reason I ask is that the documentation often says things like "turn off boundscheck
for this function," making me wonder whether it only applies to the next function defined.
In other words, do I need to do this:
import numpy as np
cimport numpy as np
cimport cython
ctypedef np.float64_t DTYPE_FLOAT_t
@cython.wraparound (False) #turn off negative indexing
@cython.boundscheck(False) # turn off bounds-checking
def myfunc1(np.ndarray[DTYPE_FLOAT_t] a):
do things here
def myfunc2(np.ndarray[DTYPE_FLOAT_t] b):
do things here
Or do I need to do this:
import numpy as np
cimport numpy as np
cimport cython
ctypedef np.float64_t DTYPE_FLOAT_t
@cython.wraparound (False) #turn off negative indexing
@cython.boundscheck(False) # turn off bounds-checking
def myfunc1(np.ndarray[DTYPE_FLOAT_t] a):
do things here
@cython.wraparound (False) #turn off negative indexing
@cython.boundscheck(False) # turn off bounds-checking
def myfunc2(np.ndarray[DTYPE_FLOAT_t] b):
do things here
Thanks!
Cython code, unlike Python, must be compiled. This happens in two stages: A . pyx file is compiled by Cython to a .
Cython works by producing a standard Python module. However, the behavior differs from standard Python in that the module code, originally written in Python, is translated into C. While the resulting code is fast, it makes many calls into the CPython interpreter and CPython standard libraries to perform actual work.
The Cython language is a superset of Python that compiles to C, yielding performance boosts that can range from a few percent to several orders of magnitude, depending on the task at hand. For work that is bound by Python's native object types, the speedups won't be large.
Cython is an optimising static compiler for both the Python programming language and the extended Cython programming language (based on Pyrex). It makes writing C extensions for Python as easy as Python itself. Cython gives you the combined power of Python and C to let you.
The documentation states that if you want to set a compiler directive globally, you need to do so with a comment at the top of the file. eg.
#!python
#cython: language_level=3, boundscheck=False
The manual does not say explicitly, but these directives are using decorator notation. In plain Python,
@decorator2
@decorator1
def fn(args):
body
is syntactic sugar for
def fn(args):
body
fn = decorator2(decorator1(fn))
So my expectation is that the directives work like that, which would mean that they apply only to the next function.
The Cython manual also says that the compiler directives can be used in with
statements. What it doesn't say, unfortunately, is whether those can appear at top level:
with cython.wraparound(False), cython.boundscheck(False):
def myfunc1(np.ndarray[DTYPE_FLOAT_t] a):
do things here
def myfunc2(np.ndarray[DTYPE_FLOAT_t] b):
do things here
might be what you're looking for, or then again it might be a syntax error or a no-op. You're going to have to try it and see.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With