-
Notifications
You must be signed in to change notification settings - Fork 187
take better advantage of static compilation #167
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
I've been thinking about it, and maybe the best approach is to pick a specific Advantages:
Disadvantages:
cc: @malmaud, @jakebolewski |
+1, as long as it's clearly documented. Maybe export an intuitively-named function to delete the cache and rebuild against the current runtime environment? In the long term, I have been wondering if it might make sense to integrate an Anaconda python distribution with the Julia package manager, so the Python distribution is in a known location and configuration. Advanced users could override this to point to a different Python environment, similar to the situation with BLAS in Julia today. That might help with the constant IJulia problems people experience. |
The rebuild has to be done when the PyCall module is not loaded yet, so I think we are stuck with |
The user benefit here in terms of performance trumps the downside of statically picking one libpython to use. If you are doing serious work, switching python versions I feel is pretty rare. |
Okay, I have a working branch that does this. With I'm having trouble figuring out how to get it down further. I tried adding lots of for T in (Int, Float64, Complex{Float64}, Bool, ASCIIString, UTF8String, Array{Float64}, Dict{ASCIIString, I\
nt}, Function, IO, @compat(Tuple{Int,Float64}), StepRange{Int,Int}, Dates.DateTime)
precompile(PyObject, (T,))
precompile(convert, (T, PyObject))
end
precompile(pycall, (PyObject, Type, Int))
precompile(pyimport, (ASCIIString,))
precompile(pywrap, (PyObject, Symbol))
precompile(__init__, ())
precompile(array2py, (Array{Int,3},))
precompile(py2array, (Type, PyObject))
precompile(writedims, (IO, PyBuffer, Int, Int)) @vtjnash, is there any way to profile the loading time to figure out where it is going? |
Hmm, looks like about 1.5 seconds of the remaining 2 seconds is happening inside |
Okay, it looks like 0.8 seconds were being taken to compile 6 functions: global const jl_Function_call_ptr =
cfunction(jl_Function_call, PyPtr, (PyPtr,PyPtr,PyPtr))
global const pyio_repr_ptr = cfunction(pyio_repr, PyPtr, (PyPtr,))
global const pyjlwrap_dealloc_ptr = cfunction(pyjlwrap_dealloc, Void, (PyPtr,))
global const pyjlwrap_repr_ptr = cfunction(pyjlwrap_repr, PyPtr, (PyPtr,))
global const pyjlwrap_hash_ptr = cfunction(pyjlwrap_hash, Uint, (PyPtr,))
global const pyjlwrap_hash32_ptr = cfunction(pyjlwrap_hash32, Uint32, (PyPtr,)) The time for these lines is cut down to 0.27 seconds by precompiling them: precompile(jl_Function_call, (PyPtr,PyPtr,PyPtr))
precompile(pyio_repr, (PyPtr,))
precompile(pyjlwrap_dealloc, (PyPtr,))
precompile(pyjlwrap_repr, (PyPtr,))
precompile(pyjlwrap_hash, (PyPtr,))
precompile(pyjlwrap_hash32, (PyPtr,)) However, it's a bit surprising that |
I love the speed increase and I'm cool with re-building PyCall to use a different Python, but unfortunately that commit is breaking PyCall in my virtual environment even when I don't change environments between Julia sessions: ~❯ workon py3
(py3)~❯ julia
julia> Pkg.build("PyCall")
INFO: Building PyCall
INFO: PyCall is using python (Python 3.4.3) at ~/.virtualenvs/py3/bin/python, libpython = libpython3.4m
julia> using PyCall
julia> # works great
julia> ^D
(py3)~❯ julia
julia> using PyCall
WARNING: error initializing module PyCall:
ErrorException("cglobal: could not find symbol PyCObject_FromVoidPtr in library libpython3.4m") That's even before using any Base.compile magic. Is some sort of PATH being lost between those Julia sessions? [Just saw the README updates so will have a look through those and see if the answer is there] |
@swt30, good question. The only environment variable that is set in the build script is |
@swt30, what does |
Opened issue #173 with more details |
Closing this issue. If there are other ways to improve static compilation, they can be separate issues. |
From JuliaPy/PyPlot.jl#143, almost all the time to load PyPlot is eliminated if I put
pyinitialize()
at the end of PyCall.jl.However, it goes back to 3.8 seconds (vs. 7.2 seconds without precompilation) if I put
pyinitialize()
in__init__
(which is where it belongs if I'm going to execute it automatically, since it needs to initialize lots of things at runtime.Is there a way to re-arrange things so that we get more benefit from precompilation while still being safe?
The text was updated successfully, but these errors were encountered: