You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
as you may know, we encountered some serious issues when attempting to port
Numba to Python 3.10. This issue will serve as a summary of existing challenges
and also as a central reference issue with links to all existing branches and
PRs.
The story so far
Supporting new Python versions for Numba is always somewhat involved. The main
reason for this is that Numba interfaces to Python via the bytecode, which is
not a stable interface/contract. In the 3.10 case, the change that caused the
most headaches was:
Specifically, the part of that change that now causes the CPython bytecode
optimizer to inline return statements. I.e. the following feature:
/* If this block ends with an unconditional jump to an exit block,
* then remove the jump and extend this block with the target.
*/
static int
extend_block(basicblock *bb) {
if (bb->b_iused == 0) {
return 0;
}
struct instr *last = &bb->b_instr[bb->b_iused-1];
if (last->i_opcode != JUMP_ABSOLUTE && last->i_opcode != JUMP_FORWARD) {
return 0;
}
if (last->i_target->b_exit && last->i_target->b_iused <= MAX_COPY_SIZE) {
basicblock *to_copy = last->i_target;
last->i_opcode = NOP;
for (int i = 0; i < to_copy->b_iused; i++) {
int index = compiler_next_instr(bb);
if (index < 0) {
return -1;
}
bb->b_instr[index] = to_copy->b_instr[i];
}
bb->b_exit = 1;
}
return 0;
}
Perhaps the easiest way to think about this is with the following Python source
example (importantly: note that CPython optimizes this at the Bytecode level, not at the
syntax or AST levels! This is for illustration only):
with objmode:
if a == 1:
b = 1
elif a == 2:
b = 2
else a == 3:
b = 3
return b
with objmode:
if a == 1:
b = 1
return b
elif a == 2:
b = 2
return b
else a == 3:
b = 3
return b
Unfortunately, in the with objmode we can not allow return statements,
since the code within the statement will be lifted out and executed in
object-mode so as to get access to interpreter features. So this bytecode
optimization renders this Numba feature useless, since the return will be
inlined! Worse yet: there is no way for Numba to tell if this was a bytecode
optimizer action or something the user intended! Incidentally, there is a way
to defeat this optimization, by making the return block big enough (see the
code snippet above for MAX_COPY_SIZE) however this is too rudimentary and can
probably only be used to adapt a few failing tests.
Effectively, Numba needed a way to undo the optimization caused by CPython and
as a precursor to that, would need to understand where a with-context begins
and where it ends. However much of this logic was based on heuristics and so
had to be overhauled to facilitate better control flow analysis.
Running the tests
Anaconda provides (at the time of writing) a Python 3.10 binary and associated
compilers on at least Linux and OSX so that can be used for testing.
Compiling Numba requires Numpy. However, the only Numpy's available (at the
time of writing) for 3.10 were 1.21.3 and 1.21.4 via conda-forge. Note however,
that both of these releases do appear buggy:
Dear all,
as you may know, we encountered some serious issues when attempting to port
Numba to Python 3.10. This issue will serve as a summary of existing challenges
and also as a central reference issue with links to all existing branches and
PRs.
The story so far
Supporting new Python versions for Numba is always somewhat involved. The main
reason for this is that Numba interfaces to Python via the bytecode, which is
not a stable interface/contract. In the 3.10 case, the change that caused the
most headaches was:
https://bugs.python.org/issue44626
Specifically, the part of that change that now causes the CPython bytecode
optimizer to inline return statements. I.e. the following feature:
Ref: https://github.com/python/cpython/blob/d41abe8/Python/compile.c#L7533-L7558
This change was noticed early during the porting process. It turned out to
cause the most headaches for the
with objmode
context manager:https://numba.readthedocs.io/en/stable/user/withobjmode.html?highlight=objmode#the-objmode-context-manager
Perhaps the easiest way to think about this is with the following Python source
example (importantly: note that CPython optimizes this at the Bytecode level, not at the
syntax or AST levels! This is for illustration only):
Unfortunately, in the
with objmode
we can not allowreturn
statements,since the code within the statement will be lifted out and executed in
object-mode so as to get access to interpreter features. So this bytecode
optimization renders this Numba feature useless, since the
return
will beinlined! Worse yet: there is no way for Numba to tell if this was a bytecode
optimizer action or something the user intended! Incidentally, there is a way
to defeat this optimization, by making the return block big enough (see the
code snippet above for
MAX_COPY_SIZE
) however this is too rudimentary and canprobably only be used to adapt a few failing tests.
Effectively, Numba needed a way to undo the optimization caused by CPython and
as a precursor to that, would need to understand where a with-context begins
and where it ends. However much of this logic was based on heuristics and so
had to be overhauled to facilitate better control flow analysis.
Running the tests
Anaconda provides (at the time of writing) a Python 3.10 binary and associated
compilers on at least Linux and OSX so that can be used for testing.
Compiling Numba requires Numpy. However, the only Numpy's available (at the
time of writing) for 3.10 were 1.21.3 and 1.21.4 via conda-forge. Note however,
that both of these releases do appear buggy:
numpy/numpy#20376
Live branches
At the time of writing the following branches were live:
Python 3.10 changes for things unrelated to with-statements:
Python3.10 v2 #7557
With-detection for <= 3.9:
refactor with-detection logic #7498
With-detection for == 3.10:
Refactor with detection py310 #7560
If you need it (due to lack of 1.20 binaries): Python 1.21.
NumPy 1.21 support #7483
Dead branches
The text was updated successfully, but these errors were encountered: