1

I've been trying for several days to get @jit working to speed up my code. Finally I came across this, describing adding @jit to object methods: http://williamjshipman.wordpress.com/2013/12/24/learning-python-eight-ways-to-filter-an-image

I have a class called GentleBoostC and I want to speed up the method within it that's called train. train accepts three arguments (a 2D array, a 1D array, and an integer), and returns nothing.

This is what I have in code:

import numba
from numba import jit, autojit, int_, void, float_, object_


class GentleBoostC(object):
    # lots of functions

    # and now the function I want to speed up
    @jit (void(object_,float_[:,:],int_[:],int_)) 
    def train(self, X, y, H):
        # do stuff

But I keep getting an indentation error, pointing to the line that defines the train function. There is nothing wrong with my indents. I have re-indented my entire code. And if I comment out the line with @jit, then there are no problems.

Here's the exact error:

   @jit (void(object_,float_[:,:],int_[:],int_))
  File "C:\Users\app\Anaconda\lib\site-packages\numba\decorators.py", line 224, in _jit_decorator
    nopython=nopython, func_ast=func_ast, **kwargs)
  File "C:\Users\app\Anaconda\lib\site-packages\numba\decorators.py", line 133, in compile_function
    func_env = pipeline.compile2(env, func, restype, argtypes, func_ast=func_ast, **kwds)
  File "C:\Users\app\Anaconda\lib\site-packages\numba\pipeline.py", line 133, in compile2
    func_ast = functions._get_ast(func)
  File "C:\Users\app\Anaconda\lib\site-packages\numba\functions.py", line 89, in _get_ast
    ast.PyCF_ONLY_AST | flags, True)
  File "C:\Users\app\Documents\Python Scripts\gentleboost_c_class_jit_v5_nolimit.py", line 1
    def train(self, X, y, H):
    ^
IndentationError: unexpected indent
BenMorel
  • 34,448
  • 50
  • 182
  • 322
user961627
  • 12,379
  • 42
  • 136
  • 210
  • Run your script with `python -tt`. You probably **do** have indentation problems. And what does `cat -eT filename.py` show? Look at both the `@jit` line and the surrounding context. – Martijn Pieters Sep 05 '14 at 10:17
  • Then why does it work with no issues at all when I comment out the @jit line? Anyway, how can I use python -tt? I'm running python using Anaconda's Spyder - how would I do it from there? – user961627 Sep 05 '14 at 10:19
  • Two options: either the `@jit` line mixes tabs and spaces inconsistent with the other lines, or you are using an ancient Python version that doesn't yet support decorators. – Martijn Pieters Sep 05 '14 at 10:20
  • I'm using Python 2.7 – user961627 Sep 05 '14 at 10:22
  • Is my @jit line correct though? – user961627 Sep 05 '14 at 10:22
  • Note that you didn't include the full error message, so I am making (educated) guesses here. I could be guessing wrong, so please do include the full error message. – Martijn Pieters Sep 05 '14 at 10:23
  • I have not used that specific decorator, but the *syntax* looks fine. – Martijn Pieters Sep 05 '14 at 10:23
  • Just edited the question to add the error. Also, I've copy-pasted the whitespace on the @jit line and other method definition lines and pasted it before def train(...) – user961627 Sep 05 '14 at 10:26
  • Ah, interesting, the `@jit` decorator tries to compile the code. I suspect now that it doesn't support *methods*, only top-level *functions*. – Martijn Pieters Sep 05 '14 at 10:31
  • I cannot find anything specific in the documentation about methods, but all examples are applied to *functions* only (outside a class context). – Martijn Pieters Sep 05 '14 at 10:34

1 Answers1

2

From what I can see from the documentation, you cannot apply the decorator to a method; the error you see is from the JIT parser not handling the source code indentation when not in the context of a class statement.

If you want the body of that method to be compiled, you'll need to factor it out to a separate function, and call that function from the method:

@jit(void(object_, float_[:,:], int_[:], int_)) 
def train_function(instance, X, y, H):
    # do stuff

class GentleBoostC(object):
    def train(self, X, y, H):
        train_function(self, X, y, H)    
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • But the train method accesses many class data members, and it affects existing members... so does this mean I would need to pass them all as parameters and then return the affected things as well? – user961627 Sep 05 '14 at 10:40
  • @user961627: That's why the `train_function` function accepts an `instance` first argument. It is the same object as `self`, I justs chose a different name to distinguish it from the common convention for the first arguments of methods. – Martijn Pieters Sep 05 '14 at 10:42
  • There's a follow up issue now: http://stackoverflow.com/questions/25685916/cannot-coerce-to-or-from-object-in-nopython-context-error-after-python... does have anything to do with limited support for objects or something? – user961627 Sep 05 '14 at 12:28
  • To keep the function within the class body, one can make it a static method of the class, as shown in https://stackoverflow.com/a/52722636 – Hugues Jan 02 '21 at 05:49