-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nested jit annotations #3332
Comments
Thanks for the report. On Numba 0.40.0, this seems to just work under from numba import njit
def test():
state = 0
def sub(param):
nonlocal state
state += param
for i in range(100):
param = i
sub(param)
print(state)
print(test())
print(njit()(test)()) output:
If
I think this is a result of the looplifting pass running before the closure inlining pass, which means that if there's a closure present ( |
As to your actual query about state etc, Numba 0.40.0 has a new feature, |
@stuartarchibald I have just upgraded to 0.40.0, but still have the same problem. Have you seen that there is a second annotation on the sub function? Also, I cannot use nopython mode for the test function itself. I will have a look at objectmode later. |
Yes, I saw that, it's currently illegal/unsupported behaviour, hence me removing it as it looked like it would inline fine under |
I was able to solve the problem with objmode. Just curious, why is it necessary to provide the return types when they can be figured out automatically for function arguments? Also, I run into a limitation. I have a pandas data frame with different data types (floats and bools) for which I want to use the numpy array in the numba optimised code. |
One more idea. For my use case, the following pattern would be very useful: def gen():
while True:
yield 1
@njit
def test():
with objmode(g="object"):
g = gen()
while True:
with objmode(val="int"):
val = next(g)
# Do something with val The variable |
One last question: Is it possible to return a list or tuple of arrays from objmode? I have tried |
Perhaps you may be running some function in object mode where type inference can't follow what would be returned? This is also an experimental feature, things may change :)
Think this comes out as a NumPy array of dtype
but this obviously incurs cost. Another option is to use the
Thanks, IIRC there are some plans on the horizon for thinking about pass through cases.
Is this the sort of thing you are after? : from numba import njit, objmode
import numpy as np
@njit
def test():
with objmode(val='List(float64[:])'):
val = [np.arange(10.), np.ones(4)]
return val
print(test()) or do you mean you want the return statement in the |
Makes all sense.
No, this is exactly what I wanted. |
hmmm, that should probably be documented, thanks for raising it, I've opened a ticket #3349. Basically, whatever string you write gets from numba import njit, objmode
import numpy as np
@njit
def test():
with objmode(val='UniTuple(float64[:], 2)'):
val = (np.arange(10.), np.ones(4))
return val
print(test()) |
I see. Thank you very much for your excellent help! |
No problem, thanks for using Numba :) |
Sorry, I have one more question: It seems like print(vals.shape) # (10,)
print(vals.dtype) # (numpy.record, [('index', '<i8'), ('a', '<f8'), ('b', '?')])
print(numba.typeof(vals)) # unaligned array(Record([('index', '<i8'), ('a', '<f8'), ('b', '|b1')]), 1d, C)
print(numba.from_dtype(vals.dtype)) # Record([('index', '<i8'), ('a', '<f8'), ('b', '|b1')]) I have tried again various type string combinations for objmode, but could not get it running. Would you mind explaining in more details, how I can determine the type string from the information above? |
hmmm, this was hard. I'm not hugely familiar with the recarray impl in Numba so there may be a better way. Independent of this, the str const constraint makes it hard to deal with more advanced types, I'll raise this at the next core developer meeting (but also acknowledge that this is a new, under development and generally experimental feature). from numba import njit, objmode, typeof, from_dtype, types, numpy_support
import numpy as np
from pandas import DataFrame
df = DataFrame(data = {'col1':[1., 2.], 'col2':[np.bool(1), np.bool(0)]})
pdrec = df.to_records()
dt = numpy_support.from_struct_dtype(pdrec.dtype)
def rec2str(rec):
attrs = ['descr', 'fields', 'size', 'aligned']
subsmap = {}
for x in attrs:
subsmap[x] = str(getattr(rec, x))
subsmap['dtype'] = rec.dtype.descr
template = "Record(\"{descr}\", {fields}, {size}, {aligned}, {dtype})"
ret = template.format(**subsmap)
# make sure it's valid
eval(ret, {}, types.__dict__)
return ret.replace('"','\\"')
# This gives the record type to paste in the `objmode` type annotation.
print("Formatted str const: %s" % rec2str(dt))
@njit
def test_record_get(recarr):
with objmode(f="Record(\"[('index', '<i8'), ('col1', '<f8'), ('col2', '|b1')]\", {'index': (int64, 0), 'col1': (float64, 8), 'col2': (bool, 16)}, 17, False, [('index', '<i8'), ('col1', '<f8'), ('col2', '|b1')])"):
f = recarr[1]
return f
@njit
def test_record_slice(recarr):
with objmode(g= "Array(Record(\"[('index', '<i8'), ('col1', '<f8'), ('col2', '|b1')]\", {'index': (int64, 0), 'col1': (float64, 8), 'col2': (bool, 16)}, 17, False, [('index', '<i8'), ('col1', '<f8'), ('col2', '|b1')]), 1, 'C')"):
g = recarr[1:]
return g
print(test_record_get(pdrec))
print(test_record_slice(pdrec)) ping @sklam any ideas for a better way? |
(replying to #3332 (comment)) It's definitely too difficult to use. This is where we need to do something like |
@sklam Yes, this would be useful (at first, I even thought that I could use the current numba.typeof for this). However, I still think, numba should just figure out the type by itself similar as for function arguments. Then users don't have to deal with it at all. |
I have code with a structure like the example below:
Because of the nonlocal
state
variable, thetest
function has to be jitted. Otherwise, I would just remove the first annotation because what really matters is thesub
function. Therefore, I wanted to to enable thenopython
mode for it, which unfortunately fails with an error:In the real code, there are lots of state variables. If there is no better solution, I will probably just use a list which I can pass around to share the state. Nested
numba.jit
annotations would be much more convenient though. What do you think?The text was updated successfully, but these errors were encountered: