Skip to content
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

IO from python-spawned threads causes deadlocks #540

Open
lassepe opened this issue Aug 18, 2024 · 1 comment
Open

IO from python-spawned threads causes deadlocks #540

lassepe opened this issue Aug 18, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@lassepe
Copy link
Contributor

lassepe commented Aug 18, 2024

Description

Carrying over from #539

The following code reaches a deadlock:

from concurrent.futures import ThreadPoolExecutor, as_completed
from juliacall import Main as jl

jl.seval(
    """
function my_sqr()
    println("Julia get's stuck at this print statement issued from thread $(Threads.threadid())")
    a = rand(10)
    for ii in 1:size(a, 1)
        a[ii] = a[ii]^2
    end
    return sum(a)
end
"""
)

pool = ThreadPoolExecutor(2)

fs = {pool.submit(jl.my_sqr): ix for ix in range(10)}
for future in as_completed(fs):
    print("running")
    rank = fs[future]
    results = future.result()
    print("done")
    print(results)

Potential Fix

Adding ccall(:jl_enter_threaded_region, Cvoid, ()) as suggested in #539 (comment) fixes this issue but not the original one of #539.
PythonCall may consider to invoke jl_enter_threaded_region behind the scenes.

@lassepe lassepe added the bug Something isn't working label Aug 18, 2024
@cjdoris
Copy link
Collaborator

cjdoris commented Aug 22, 2024

Indeed the semantics of how Julia and Python threads interact have not been totally worked out yet. In particular, Julia has a task scheduler which doesn't really like running on foreign threads. I think there are functions to let Julia adopt Python-created threads but I've not tried them out.

However for me, the advice in this section of the docs successfully makes the example work. I also needed to do pool.submit(jl.my_sqr._jl_call_nogil) to release the GIL while calling my_sqr - without it, the GIL is held by the Julia thread that is deadlocked, preventing the main Python thread from doing anything.

I would of course like to avoid having to explicitly do this yielding loop to make the threads run Julia code properly. Thanks for pointing out jl_enter_threaded_region. Hopefully some combination of this and thread adoption will make this all work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants