c14369
c14369

Reputation: 53

Do locally set Cython compiler directives affect one or all functions?

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!

Upvotes: 5

Views: 2235

Answers (2)

Dunes
Dunes

Reputation: 40833

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

Upvotes: 7

zwol
zwol

Reputation: 140786

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.

Upvotes: 2

Related Questions