-
Notifications
You must be signed in to change notification settings - Fork 34
headless rendering #146
Comments
This is huge. Given that so much of our visualization needs to happen on a server, it's been my main concern about taking the leap to GLVisualize. Thanks for working on this! |
@timholy would you like to explore this some more? is there an easy test we can do? |
Yes we do have X server installed on our headless systems :) |
I should add that we use Tesla GPUs in most of these systems, which might complicate things. We can avoid using the Teslas for this if needed. But if I understand #117 correctly then we may be able to use the Teslas? |
Great! using GLVisualize
window = glscreen(resolution = (500, 500), visible = false) # visible = false is optional
_view(visualize(rand(Float32, 32, 32)))
yield()
GLWindow.poll_glfw()
GLWindow.render_frame(window)
GLWindow.swapbuffers(window)
GLWindow.screenshot(window, path = homedir() * "/test.png") Make sure you're up to date with: foreach(x-> Pkg.checkout(x), ("GLWindow", "GLAbstraction", "GLVisualize", "GLFW")) |
You can also run the whole testsuite (Pkg.test("GLVisualize")), when you set these environment variables: ENV["CI"] = "true"
ENV["CI_REPORT_DIR"] = "path/where/renders/will/be/stored" |
Really sorry I missed that ping 6 days ago. If I tim@cannon:~$ glxinfo | grep OpenGL
X Error of failed request: GLXBadContext
Major opcode of failed request: 154 (GLX)
Minor opcode of failed request: 6 (X_GLXIsDirect)
Serial number of failed request: 22
Current serial number in output stream: 22
tim@cannon:~$ I can try running it locally too. The server is in a closet, so obviously we don't want to sit in front of it for hours, but it does have an attached monitor and keyboard. |
That doesn't look too good :D |
If I'm sitting in front of the server using the keyboard and monitor, I get this
|
interesting, that looks much better! I guess this means, you simply have to start the X-Server! |
BTW we can also buy a dedicated video card; it will compete for slot space with other things (e.g., compute GPUs). |
It walks you through all different gotchas, not sure which ones are relevant on your specific system ;) |
Will try. I have a couple of other things I have to do first, but back at you later today. |
doesn't seem to be needed :)
That means it should be possible to get hardware accelerated OpenGL in some way! |
I just verified that GLVisualize works on that server if you're sitting in front of it. 🎆 Thanks for the link re remote access! Since that will involve rebooting the server, there will need to be some checking/scheduling with users of the server. |
Great! Can't be that hard then! |
So I got this working on one of our Tesla servers. Instead of following the ArrayFire instructions in the end I decided to use VirtualGL. Instructions:
(You can find the bus ID with
You can test that it's working by comparing the output of without:
with:
There is one issue with this. VirtualGL doesn't like it when GLVisualize windows are closed. When running the tests for GLVisualize everything works fine (I can play with the cat) but when I close the window I get this error: julia> Pkg.test("GLVisualize")
INFO: Computing test dependencies for GLVisualize...
INFO: Installing Highlights v0.2.1
INFO: Testing GLVisualize
Now showing rotate_robj.jl:
[VGL] ERROR: in readback--
[VGL] 254: Window has been deleted by window manager
=============================[ ERROR: GLVisualize ]=============================
failed process: Process(`/home/cody/src/julia/usr/bin/julia -Cnative -J/home/cody/src/julia/usr/lib/julia/sys.so --compile=yes --depwarn=yes --check-bounds=yes --code-coverage=none --color=yes --compilecache=yes /home/cody/v0.5_for_seg/v0.5/GLVisualize/test/runtests.jl`, ProcessExited(1)) [1]
================================================================================
INFO: Removing Highlights v0.2.1
ERROR: GLVisualize had test errors
in #test#61(::Bool, ::Function, ::Array{AbstractString,1}) at ./pkg/entry.jl:740
in (::Base.Pkg.Entry.#kw##test)(::Array{Any,1}, ::Base.Pkg.Entry.#test, ::Array{AbstractString,1}) at ./<missing>:0
in (::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#test,Tuple{Array{AbstractString,1}}})() at ./pkg/dir.jl:31
in cd(::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#test,Tuple{Array{AbstractString,1}}}, ::String) at ./file.jl:59
in #cd#1(::Array{Any,1}, ::Function, ::Function, ::Array{AbstractString,1}, ::Vararg{Array{AbstractString,1},N}) at ./pkg/dir.jl:31
in (::Base.Pkg.Dir.#kw##cd)(::Array{Any,1}, ::Base.Pkg.Dir.#cd, ::Function, ::Array{AbstractString,1}, ::Vararg{Array{AbstractString,1},N}) at ./<missing>:0
in #test#3(::Bool, ::Function, ::String, ::Vararg{String,N}) at ./pkg/pkg.jl:258
in test(::String, ::Vararg{String,N}) at ./pkg/pkg.jl:258 |
This sheds some light on the error: |
I'm thinking maybe there's something we can do within GLVisualize to prevent the above error. Per the link that I posted, maybe we can call |
I suspect that the issue is that the destroy call is being generated by the window manager on the client rather than the application on the server---so the server doesn't realize the window has been closed, tries to draw on it, and gets an error. If you run using Ideally it would be nice not to have to set up any communication between VirtualGL and GLFW; instead, it would be great if GLFW would emit some signal that we can catch in a callback and terminate rendering. That will depend on where the failure occurs. Another option might be to wrap this loop in a |
See also http://www.glfw.org/docs/latest/window_guide.html#window_close. GLFW.jl doesn't yet wrap that function, but it would only be a few lines. I'm not sure whether GLFW actually gets the signal in time, however; it's possible that GLFW only learns about the problem after the "pipe" is broken and it's too late to do anything about it. You could also try commenting out the |
Well I didn't solve this, but I understand the problem a bit better. Note that one can replicate the problem without GLVisualize, simply by using virtualgl to run the example script in the GLFW.jl README.
It seems we have to detect it before it's thrown.
Are you referring to
So we want to prevent virtualgl from getting the signal at all. There are examples of how to do this using calls to Xlib--here is one--but glfw seems to take a similar approach here, so I don't understand why glfw's interception is not sufficient. Maybe there's a difference between "intercepting" and sharing a signal, but I don't see how to distinguish between the two. For now the workaround is to never close windows with X window buttons--always call |
I meant If this is too troublesome we should file an issue with VirtualGL. |
It seems that several people have raised the issue with virtualgl before, but the developers are adamant that they are doing the right thing. Could it be a bug in the way GLFW handles X11 window closing? |
Hmm, but if I do this: julia> using GLFW
julia> window = GLFW.CreateWindow(800, 600, "Context creation")
GLFW.Window(Ptr{Void} @0x000000000304afe0,Function[#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef,#undef])
julia> while !GLFW.WindowShouldClose(window)
GLFW.PollEvents()
end then when I click the close button, the loop terminates but the window stays open; I have to call |
Ah, thanks for explaining. Assuming the above demo is broken if you run it over VirtualGL, perhaps we should ask the devs how they think we should solve this? |
So...surprisingly, your demo works for me! The key difference between that and the demo in the GLFW.jl README is that you don't call That seems bizarre to me. Do you understand why the current context might be important? |
Hmm, I'm not the best person to advise you on this, @SimonDanisch knows much more. Maybe try the |
My guess is that somehow we're fooling VirtualGL--maybe it only monitors the thread associated with the active context? If so a workaround might be to remove the current context by passing NULL to that function (see docs) before we destroy the window EDIT: That workaround seems impossible to use. It only works if we ensure that the current context does not match the window whenever the user might click the close button (all the time). I can bring the issue over to the VirtualGL folks, but I want to make sure that I can articulate the proper question to ask them. Simon, maybe you could help me form the question? |
Any thoughts here, @SimonDanisch? |
Sorry I lost a bit track of this issue. I will look into it after lunch! |
Seems like you two have already done great detective work. I can't add much to it. |
Cool thanks Simon! I've opened an issue with VirtualGL. I tried to cc both of you but the @ mechanism wasn't working from there for some reason. |
VirtualGL just posted a new pre-release build that fixes the issue, so we are in business! |
I've tried following these steps fairly carefully, but I can't seem to get it to work. When I run
Any help would be appreciated. Cheers |
It looks like a dependency problem -- either dependencies are missing or somehow the path isn't getting set correctly. Am I correct that you're using CentOS? I've never used it before, so the setup may be different than what worked on Ubuntu for me. It looks like the dependency problems are all dependencies of julia. Is the command |
Hi Cody, Thanks for getting back to me. Oddly enough I'm running Ubuntu 16.04 LTS. I'm not sure why centos is appearing in the output. Perhaps I've inadvertently installed the wrong version of VirtualGL? Yes, I've got |
@Cody-G is right, that's all julia related. Does this even run without vglrun?
Well, I don't know what's going on, but the path, |
Yes, I followed the instructions on this page when installing Julia: https://julialang.org/downloads/platform.html |
And went for the symbolic link option |
I've had another stab at getting this to work. This time I built Julia from source instead of using a downloaded linux binary. This has solved the problems that I was experiencing previously and I can now run I can run Any advice would be appreciated. |
Well, GR doesn't use OpenGL, so it should work independent of the GPU setup. |
I've decided to go for hardware accelerated headless rendering only for now...
I found these resources, which should be relatively easy to try out, if one has the correct hardware:
https://devblogs.nvidia.com/parallelforall/egl-eye-opengl-visualization-without-x-server/
https://arrayfire.com/remote-off-screen-rendering-with-opengl/
EDIT: I got GLFW figured out
I will try out the last solution hopefully soon and set up https://github.com/SimiDCI/GLVisualizeCI.jl on a machine :)
CC: @timholy, @vchuravy
The text was updated successfully, but these errors were encountered: