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
Segfault when using assert with parallel=True #9029
Comments
This happens when |
ping @DrTodd13 |
@99991 You can do the body of your nested for loops in another function and that should solve the problem. I wonder if this MWR obscures the issue a bit because parallelizing a "max" over 3 elements isn't very useful and in fact will slow the program down. Can the outer loops be collapsed into one loop with pndindex or one of the loops here made into a prange? If so, then the "max" inside the loop nest will be lowered sequentially and the problem will also go away. We think we know why this segfault is occurring and the fix is probably moderately difficult and we will be working on it but wanted to give some workarounds in the meantime. |
Thank you!
Definitely. But I doubt that anyone would read the 700 lines of filter kernels that this has been condensed from and removing the
Perhaps, but the original code would then need to pass about 16 parameters, which is a bit much I think.
The original code computes something for every pixel of an image without any pixel dependencies (embarrassingly parallel), so both of the loops could make use of Anyway, when using from numba import njit, prange
import numpy as np
import os
os.environ["NUMBA_PARALLEL_DIAGNOSTICS"] = "4"
@njit(parallel=True)
def foo():
for y in prange(1000):
for x in range(1000):
values = np.zeros(3)
i = np.argmax(values)
assert i >= 0
foo() I do not know how to read the diagnostics, but it seems that something is still happening with argmax. |
@DrTodd13 Is it likely we can fix this by 0.58? |
@99991 @stuartarchibald This doesn't appear to be documented anywhere but the parallelism code will only convert a prange to run in parallel if it is able to rewrite the loop into a parfor and it can only do that if there is only one exit from the loop. Because you have an assert in there, there is more than 1 exit from the loop. If you think about it, to some extent an assert here is ill-defined because normally you'd hit the first such extraneous control flow but in parallel you might hit a different assert or a different element would cause the assert. I'm not sure this was planned but it is a bit fortunate because the parfor is turned into a gufunc and gufuncs swallow exceptions anyway. So, if you take out the assert then the parfors in the loop body (which are the zeros and the argmax) are lowered sequentially and you don't get a segfault. Suggestions Stuart? |
@DrTodd13 maybe:
How does that sound? |
I added documentation and a warning when a prange loop isn't parallelized (also in PR 9048). I also fixed the stack overflow issue in 9048. |
The following code triggers a segfault. Tested on Ubuntu 22.04 with Numba 0.56.4 and Numba 0.57.0.
visible in the change log (https://github.com/numba/numba/blob/main/CHANGE_LOG).
i.e. it's possible to run as 'python bug.py'.
The text was updated successfully, but these errors were encountered: