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
Conditional with gil
and threading
#3554
Comments
Note that you do not need to write the Looking at the C code that Cython generates from the example that you linked to, the difference is that the function that uses The GIL acquisition is unconditionally inserted here, as a try-finally statement wrapping the whole function body: cython/Cython/Compiler/ParseTreeTransforms.py Lines 1861 to 1872 in f09e61a
and gets released here, after generating the function code: cython/Cython/Compiler/Nodes.py Lines 2145 to 2148 in f09e61a
I don't know how difficult it would be to detect the needless acquire and avoid it, but in any case, I consider it a bug that this happens unconditionally. in the success case, it should run through the function without touching the GIL at all. |
Thanks for the detailed answer and investigation @scoder ! |
I think the best solution is to get rid of the try-finally node and do the cleanup in |
…ion exit, e.g. for cleaning up temp variables from with-gil blocks or adding tracebacks. Closes #3554.
I think I found a better way to do this. See #3556. |
…ion exit, e.g. for cleaning up temp variables from with-gil blocks or adding tracebacks. Closes #3554.
@rth @webber26232 could you try #3556 to see if it resolves the performance issue for you? I looked at the generated code and the success code path is free of GIL usage now and should be fast. |
Acquire the GIL in nogil functions only when strictly needed on function exit, e.g. for cleaning up temp variables from with-gil blocks or adding tracebacks. Closes GH-3554.
Sorry for slow response @scoder. Thank you for finding a solution and for your work on Cython in general! I can confirm that 3.0a3 which includes this fix does resolve the problem on the example in scikit-learn/scikit-learn#17038 (comment) |
Acquire the GIL in nogil functions only when strictly needed on function exit, e.g. for cleaning up temp variables from with-gil blocks or adding tracebacks. Closes cythonGH-3554.
Acquire the GIL in nogil functions only when strictly needed on function exit, e.g. for cleaning up temp variables from with-gil blocks or adding tracebacks. Closes cythonGH-3554.
Acquire the GIL in nogil functions only when strictly needed on function exit, e.g. for cleaning up temp variables from with-gil blocks or adding tracebacks. Closes cythonGH-3554.
) Closes #4637 See See #3556 * Acquire the GIL in nogil functions only when strictly needed on function exit, e.g. for cleaning up temp variables from with-gil blocks or adding tracebacks. See #3554 * Make the GIL-avoidance in 7d99b0f actually work in nogil functions and not just nogil sections. See #3558
A nogil block with a loop that uses an unlikely
with gil
statement e.g. approximately,appears work similarly to the while function not releasing gil, when using in multi-threaded code.
See more complete minimal example in scikit-learn/scikit-learn#17038 (comment)
Naively I though that since the
with gil
is never executed, performance wise this would be equivalent to the same function without thewith gil
block (or roughly that threading performance would be directly impacted by the fraction of run time where the gil is released). However it does not seem to be the case.Is this behavior expected? If so maybe the documentation section https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#acquiring-and-releasing-the-gil could be updated to mention conditional acquiring of GIL.
The text was updated successfully, but these errors were encountered: