-
Notifications
You must be signed in to change notification settings - Fork 66
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
Segfaults with frequent python calls from thread 1 on multithreaded Julia #201
Comments
I have never really tried it out, but I'm not too surprised. AFAIK it should work fine provided all the calls into the CPython API occur from the same thread (or are guarded with Do you have a MWE I can try? |
At the moment, it's definitely not minimal, but I'll see what I can cook up.
Oh, how do I do that?
I had a feeling it might be related to that - can I control where the finalizer runs? |
See #202 (comment) If you try out that branch and put |
The problem is, Python is calling an MCMC sampler written in Julia, which then calls back to evaluate the actual target function in Python. So I'd have to disable Python GC for a very long time, memory will overflow. The Julia code itself does container multithreaded operations, though I've made sure that the callbacks to Python are always originating from thread 1. Other parts of the Julia code (not calling back into Python) will use threads, but from Python, only a single algorithm is called, I I can't "inject" gc-disable/enables into the Julia code in lots of places. |
I've just released a new version including these GC functions, they are now called In your case, you should be able to do the whole optimization with GC disabled, but temporarily re-enable it within the callback function. |
Thanks a lot @cjdoris , will try it out! |
This issue has been marked as stale because it has been open for 30 days with no activity. If the issue is still relevant then please leave a comment, or else it will be closed in 7 days. |
This issue has been closed because it has been stale for 7 days. If it is still |
Why not just check in the |
I had the same problem and for me, disabling/enabling was not sufficient. I finally ended up with the following code: using PythonCall
using ThreadPools
macro pythread(expr)
quote
fetch(@tspawnat 1 begin
$(esc(expr))
end)
end
end
function babel_convert(input, informat = "cdxml", outformat = "mol")
@pythread begin
ob = pyimport("openbabel.openbabel")
conv = ob.OBConversion()
conv.SetInAndOutFormats(informat, outformat)
mol = ob.OBMol()
conv.ReadString(mol, input)
if ! Bool(mol.Has2D()) && ! Bool(mol.Has3D())
pgen = ob.OBOp.FindType("gen2D")
pgen !== nothing && pgen.Do(mol)
end
pyconvert(String, conv.WriteString(mol))
end
end I also placed this on discourse |
@cjdoris Maybe the macro Maybe, some of the open segfault issues are related and could be solved by using the macro? |
@hhaensel would this workaround also work if the Python code calls back into Julia (the called Julia code would use Julia multithreading). |
Not sure, I never used juliacall. But I guess it's safe. Meanwhile I change macro pythread(expr)
quote
fetch(@tspawnat 1 begin
PythonCall.GC.disable()
res = $(esc(expr))
PythonCall.GC.enable()
res
end)
end
end Not sure, how expensive that is performancewise. Maybe @cjdoris cann comment. |
Any idea why this doesn't seem to affect PyCall.jl? Or does PyCall force everything to run on thread 1 internally? |
It does effect PyCall, the following lines crash julia: using PyCall
for _ in 1:1000
Threads.@spawn pyimport("os")
end Also in this case macro pythread(expr)
quote
fetch(@tspawnat 1 begin
$(esc(expr))
end)
end
end
for _ in 1:1000
Threads.@spawn @pythread pyimport("os")
end What I cannot answer is, how GC is organised in PyCall and how you can make sure your variables are not garbage collected. |
Thanks! |
No idea about performance but if you do two concurrent |
I'm curious about this solution. For me I don't mind if my python code is always behind a lock, but it seems like GC happens at various points that I can't control, and then it segfaults, so I must basically avoid all threading in the whole (mostly julia) program. Could Line 57 in 6437514
It seems like something like that could make things work "automatically", though if the finalizer is never called from thread one, that would be an issue (but there could be function to do so, some |
In a complex application with high-frequency python calls I always run into
segfaults when Julia has multiple threads (e.g.
JULIA_NUM_THREADS=4
). I do make sure to only use PythonCall from thread 1 (and I use asserts to verify that) but somehow that doesn't seem to be enough. When running withJULIA_NUM_THREADS=1
, all is fine. Is PythonCall incompatible with multi-threaded Julia in general?The text was updated successfully, but these errors were encountered: