Repository navigation
Add support for arrayanalysis of tuple args. - #7398
Conversation
|
@DrTodd13 Thanks for the PR! Is there a related issue for this PR? |
|
Thanks for the patch. I wonder if adding the expression to equivalence analysis creates a problem for legitimate cases such as this: from numba import njit, pndindex
import numpy as np
@njit(parallel=True)
def test_impl(x, sz):
for i in pndindex(sz):
x[i] = 1
return x
@njit(parallel=True)
def call(x):
return test_impl(x, (10, 3)) # Only want to iterate the 3rd column
print(call(np.empty((10, 10))))where a user wants to just iterate to the 3rd column of the 2d array. |
No. It was just something that I ran across in the course of my regular work that I needed to work in Numba. |
|
@stuartarchibald If I don't make "call" njit then your example works. If I make "call" njit then I get an internal typing error at numba.core.typeinfer.CallConstraint which doesn't look related to my changes. |
I see the same, it's a chained exception, it looks a bit like: i.e. an |
|
@stuartarchibald When you make the caller Numba then the tuple (10,3) doesn't become a UniTuple of Literal[int] but a regular Tuple of two Literal[int]. Is there a reason for that? In any case, maybe that is better because you can also have a Tuple with one literal and the other a non-literal which my recent patch to this PR supports. Please have another look. I added an additional test for this mixed case (which subsumes the case of two literals). |
I think it's because the IR preserves literals into the tuple type during type inference. Lines 230 to 241 in 4a3d575 This bit: will be False as the literal values will compare False. I think this might be from trying to preserve as much constant type information as possible.
I think that this is indeed the case. |
stuartarchibald
left a comment
There was a problem hiding this comment.
Thanks for the update. I've taken a look through and have left some new comments inline. I also wonder if it'd be a good idea to include the test case from here: #7398 (comment) somewhere so as to ensure this common pattern works.
Thanks again!
| for i in numba.pndindex(sz): | ||
| x[i] = 1 | ||
| return x | ||
| sz = (10,numba.literally(10)) |
There was a problem hiding this comment.
I'm not sure that this has the desired effect. numba.literally outside of compiled code is a pass through NOP:
Lines 64 to 87 in 4a3d575
it might be necessary to close over or locally define a const to get a literal if that's the intent?
There was a problem hiding this comment.
I've added some tests and tried to generate the right tuples using what I think you were suggesting above with one literal arg but there is some lowering error I don't understand. Can you take a look at it?
…er arg tuple with mix of literal and non-literal integer. Add additional tuple tests in combination with pndindex.
… creates one loop nest with an integer index variable. In other words, it becomes much like a prange in that case.
| in_arr_typ = pass_states.typemap[in_arr.name] | ||
| if isinstance(in_arr_typ, types.Integer): | ||
| index_var = ir.Var(scope, mk_unique_var("parfor_index"), loc) | ||
| pass_states.typemap[index_var.name] = types.uintp |
There was a problem hiding this comment.
Not to be fixed in this PR. But I noticed that both njit and njit(parallel=True) will compiled and execute a pndindex driven loop where the arg supplied to pndindex is a negative integer. e.g.
@njit(parallel=True)
def test_impl(x, sz):
for i in pndindex(sz):
x[i] = 1
return x
print(test_impl(np.zeros((10, 10)), -3))
stuartarchibald
left a comment
There was a problem hiding this comment.
Thanks for the patch and fixes.
Previously, if a tuple of integers were passed in and then used in a pndindex, the parfor pass would fail because the tuple of dimension sizes didn't have an entry in array analysis. This PR adds integer tuple arguments to array analysis whereas previously only integer tuple variables were supported.