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

Slow REPL together with Makie #267

Closed
natschil opened this issue Dec 15, 2018 · 16 comments
Closed

Slow REPL together with Makie #267

natschil opened this issue Dec 15, 2018 · 16 comments

Comments

@natschil
Copy link

I'm currently using Makie with quite elaborate scenes in high resolution. I've found that sometimes stdin/stdout in the REPL is very, very slow if there is a scene window open (like every character takes a fraction of a second to be output, which is frustrating for long Julia errors). Julia itself is still fast, just the REPL is slow.

@c42f
Copy link
Contributor

c42f commented Feb 25, 2019

The Julia REPL runs in a julia Task; GLMakie also runs the GUI in a Task (screen.rendertask). In current Julia these have to share the same CPU thread via cooperative multitasking.

So whether the REPL Task will get enough resources to feel responsive depends on how good the rendering backend is at sharing the CPU. At the moment this is done here for GLMakie: https://github.com/JuliaPlots/GLMakie.jl/blob/6ea449dd1bd7878831e7086a7f20afd9e16f5b30/src/rendering.jl#L11.

From the look of this, if you have a scene which isn't meeting the target framerate, the REPL task will be scheduled only once every frame. This could be due to CPU work (ie, scene preparation due to animation etc), and there's not a whole lot which can be done about that in current julia. Other than maybe adding a few more calls to yield() in strategically chosen locations.

Alternatively it could be due to CPU blocking while the GPU does work. Ideally we'd send all the work to the GPU and then release the CPU to do other things while we're waiting. OpenGL is generally asynchronous like this but there's certain things which force it to be synchronous, such as reading rendered frames back. For example when selecting objects by using glReadPixels here: https://github.com/JuliaPlots/GLMakie.jl/blob/6ea449dd1bd7878831e7086a7f20afd9e16f5b30/src/screen.jl#L293. It looks like Simon has been fairly careful to keep the GPU work async where possible, but it could be that you've hit an edge case. Can you give a stripped down example of the problem?

@natschil
Copy link
Author

natschil commented Feb 25, 2019

Can you give a stripped down example of the problem?

I think it usually happens after call to resize!() (try e.g. resize!(scene,(3000,3000))
My guess is that nobody else is using scenes of this size. But I need them as I want to use crops of the results for a publication, and they look kind of bad unless the scene is big enough.

@SimonDanisch
Copy link
Member

Do you even need a renderloop then?

@natschil
Copy link
Author

Probably not really. It's nice to see the results of what is rendered on the screen now and then, but it isn't a big issue if I have to save them somewhere and then inspect.

@asinghvi17
Copy link
Member

What would happen if you started julia with JULIA_NUM_THREADS=2? Just out of curiosity

@SimonDanisch
Copy link
Member

Probably not really. It's nice to see the results of what is rendered on the screen now and then, but it isn't a big issue if I have to save them somewhere and then inspect.

It would be fairly simple to only render a frame on display, which should completely avoid this issue... need to figure out a nice API! Any recommendations are appreciated ;)

What would happen if you started julia with JULIA_NUM_THREADS=2? Just out of curiosity

Pretty sure that nothing will happen... How do you get the idea that something should happen?
Neither my code nor the REPL code is using threads - as a matter of fact, Julia still doesn't really support worker threads as of now, so it's almost impossible to improve the situation via threads right now :(

@asinghvi17
Copy link
Member

Dang. Just thought of it from @c42f's comment about processes sharing a thread, so I thought if you allowed Julia more threads it could split the processes.

@natschil
Copy link
Author

@SimonDanisch

For an API, how about having something like a constructor "Scene(;renderloop=[true|false])". In the case that renderloop==true Makie could do what it currently does. In the case that renderloop==false, it would only render the scene once after calls that change the scene?

@asinghvi17
Copy link
Member

@natschil could you share an MWE? I just compiled the latest build of Makie, and I'd like to test it out.

@natschil
Copy link
Author

I can't seem to reproduce it on my laptop at the moment, I'll try to reproduce it on a workstation where I've seen problems tomorrow.

@c42f
Copy link
Contributor

c42f commented Feb 26, 2019

I thought if you allowed Julia more threads it could split the processes

This is how things should work but julia's Task system is not multithreaded yet, and won't be until JuliaLang/julia#22631 (or equivalent) is merged.

@briochemc
Copy link
Contributor

I have the same REPL slowness here even with fairly small, simple plots. Using Julia v1.5.0-rc2, AbstractPlotting v0.12.5, GLMakie v0.1.8, on a 2020 macbook pro, running this MWE plot takes 13 seconds for just printing rand(20,20) (instead of 0.02 seconds when I'm not plotting stuff)... Am I doing something wrong?

using AbstractPlotting
using AbstractPlotting.MakieLayout
# Some data
x, y = 0:0.01:2π, 0:0.1:10
f(x,y) = (cos(x) + y > 9) ? NaN : cos(x) * sin(y)
data = [f(x,y) for x in x, y in y] ;
# A function to plot
function myplot(x, y, data)
    scene, layout = layoutscene(10, resolution = (300, 300))
    ax = layout[1,1] = LAxis(scene)
    heatmap!(ax, x, y, data)
    ylims!(ax, (10,0))
    return scene
end
# GLMakie plot
using GLMakie; GLMakie.activate!()
display(myplot(x, y, data))
# time to print at REPL:
@time println(rand(20,20)) # takes 13.4 seconds

@ffreyer
Copy link
Collaborator

ffreyer commented Jul 31, 2020

This issue has gotten worse since we started using vsync. You can turn that off by setting GLMakie.WINDOW_CONFIG.vsync[] = false.

@briochemc
Copy link
Contributor

briochemc commented Jul 31, 2020

This issue has gotten worse since we started using vsync. You can turn that off by setting GLMakie.WINDOW_CONFIG.vsync[] = false.

This does not help for me. I just tried (added GLMakie.WINDOW_CONFIG.vsync[] = false just before the @time println(rand(20,20))) and it still takes 13 seconds to print that.


EDIT: This works! The time-to-print has gone back to normal! Maybe make revert this change? (Thanks @ffreyer, you were correct, I had not closed the window!)

@ffreyer
Copy link
Collaborator

ffreyer commented Jul 31, 2020

You have to close the window for this to take effect

@ffreyer
Copy link
Collaborator

ffreyer commented Jul 31, 2023

This should be fixed by render on demand

@ffreyer ffreyer closed this as completed Jul 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants