Skip to content

PlotSignalConst() - faster rendering for millions of points#70

Merged
swharden merged 9 commits intoScottPlot:masterfrom
StendProg:BigSignal
Aug 6, 2019
Merged

PlotSignalConst() - faster rendering for millions of points#70
swharden merged 9 commits intoScottPlot:masterfrom
StendProg:BigSignal

Conversation

@StendProg
Copy link
Contributor

Finding MinMax in RenderHighDensity (bottleneck for large signals) using Segmented Tree.
Responsitive rendering in cost of additional memory, preprocessing time and losing ability change source signal after adding.

@StendProg StendProg changed the title Added new PlotSignalConst plot type. Responsitive rendering for tens of millions points. Added PlotSignalConst plot type. Responsitive rendering for tens of millions points. Aug 6, 2019
@swharden swharden self-requested a review August 6, 2019 19:02
@swharden swharden self-assigned this Aug 6, 2019
Copy link
Contributor

@Padanian Padanian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Searching a big population for its min and max by scrolling through the whole of it, it is efficient neither with a for cycle, nor with a segmented tree.
We need to investigate a parallel.for or a multithreading search.

Copy link
Member

@swharden swharden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really great! Signal plots render much faster with this method.

In the comments you noted a size limitation for the input array:

https://github.com/swharden/ScottPlot/blob/4af1ad885f6460818a44638be37713c07b60e440/src/ScottPlot/plottables/PlottableSignalConst.cs#L7-L13

When I try to plot 100 million points I get this exception

Exception thrown: 'System.OutOfMemoryException' in System.Core.dll
An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Core.dll

I understand why I get this exception, but someone less familiar with this plotting library may benefit from a more descriptive failure. What do you think about modifying the code to do one of:

  • throw an exception immediately if PlottableSignalConst() is instantiated with an array too large for the system
  • if the array is too large for the segmented tree method to process, use the original (non-tree-based) MinMaxRangeQuery so no exception ever happens

looking forward to hearing your thoughts!

@swharden
Copy link
Member

swharden commented Aug 6, 2019

Searching a big population for its min and max by scrolling through the whole of it, it is efficient neither with a for cycle, nor with a segmented tree. We need to investigate a parallel.for or a multithreading search.

@Padanian additional speed improvements could be made with multi-threading, but the PlotSignalConst() @StendProg proposes is remarkably faster than PlotSignal()!

@swharden swharden mentioned this pull request Aug 6, 2019
@StendProg
Copy link
Contributor Author

I try parallel.For for a fist time it gives only 2-3 times faster rendering on my 4 core. This is not enough. Anyway can make it for a PlotSignal(). PlotSignalConst works realy fast 20-30 comparasions for each interval. Bottleneck on graphics.DrawLines() not MinMaxSearch.

@StendProg
Copy link
Contributor Author

Memory limitations its c# array limitations. It's trying to allocate in memory continious block for full array. Point of search is using another data types but all algoritms will be more complex and more slow.
I will try to catch mem exception and call PlotSignal, but it also has limitations just about 2 times more points

@swharden
Copy link
Member

swharden commented Aug 6, 2019

Memory limitations its c# array limitations. It's trying to allocate in memory continuous block for full array.

Consider a situation where you create a program and it runs well on your really nice computer with lots of memory. You send your program to a client who has a really bad computer and it crashes on their computer but not yours... this is what I'd like to avoid.

What if we made this simpler by not creating a new plot object? We could just add "const" as an argument to PlotSignal():

  • if const is false, TreeMin and TreeMax are null
  • If const is true UpdateTrees() would run and populate TreeMin and TreeMax arrays
  • if UpdateTrees() crashes, TreeMin and TreeMax get set to null
  • MinMaxRangeQuery() uses the tree method only if TreeMin and TreeMax are not null, otherwise it uses the old method

What do you think?

@StendProg
Copy link
Contributor Author

StendProg commented Aug 6, 2019

Its simple to make by call base.MinMaxRangeQuery() inside MinMaxRangeQuerry in different situation.
Upgrading for now Const to call base.Min.... before tables calculated in other thread. This replace blank screen delay with chart with slow rendering delay. Also it can be always call base.Min.. if CalcTables get and catch mem Exception.

@swharden swharden changed the title Added PlotSignalConst plot type. Responsitive rendering for tens of millions points. PlotSignalConst() - faster rendering for millions of points Aug 6, 2019
autoformat, clarified comments, and moved TreesReady assignment to better spot (in case UpdateTrees() is manually re-run)
Small datasets (e.g., 1k points) were failing to render. I think it's because the way the min/max lookup works for small datasets. This fixes the rendering issue (is there a better solution?)
@swharden
Copy link
Member

swharden commented Aug 6, 2019

I updated the "plot types" demo so all the signals use PlotSignalConst(). When I did this I noticed that the signal with 1k points didn't display well. This improved it, but I don't think it's a definitive solution:

https://github.com/swharden/ScottPlot/blob/58c0ea08cf5614da38742bed4cb02779680c9885/src/ScottPlot/plottables/PlottableSignalConst.cs#L18-L22

But it made me wonder - what is the lower limit (number of points) this class can display? Should this class be expected to work with an array of 10 data points?

@StendProg
Copy link
Contributor Author

StendProg commented Aug 6, 2019

The reason is wrong indexes in calling querry. I thinked it always call (left_index < right_index)

@swharden
Copy link
Member

swharden commented Aug 6, 2019

This looks great! Thanks @StendProg!

@swharden swharden merged commit 22a2deb into ScottPlot:master Aug 6, 2019
@swharden
Copy link
Member

swharden commented Aug 7, 2019

I added a relevant section to the cookbook:

https://github.com/swharden/ScottPlot/tree/master/cookbook#signal
https://github.com/swharden/ScottPlot/tree/master/cookbook#signalconst

PlotSignal() and PlotSignalConst() were showing the same render times initially, then I realized it was because of the multi-threading. I ended-up adding a useThreading argument (which defaults true). Let me know if you find this acceptable, or if you have a better idea for how to control this behavior.

https://github.com/swharden/ScottPlot/blob/2a3781a88a6ca2fb40f0cc617162750df4b9b6fc/src/ScottPlot/plottables/PlottableSignalConst.cs#L18-L29

@StendProg
Copy link
Contributor Author

Thanks for accepting. Feel free to give better name for interface method Plot.PlotSignalConst().
PlotSignalConst() always show bigger render time in single Render() call, because you should add UpdateTrees() time to you measure. It benefits on multiple Render() calls then interacting with plot, because UpdateTrees() call ones initialy.
I dont't think users really need to control this behavor. Only if someone prefer waiting full load instead of interacting with low framerates during this delay.
Options always good, but i think 99% users prefer it set to true. Anyway it need a better name in interface function to describe functionality not realization, like fastLoad, immediatelyRender, parallelLoad, notWaitFullLoad etc. You are more familar with english words....

@StendProg StendProg deleted the BigSignal branch August 7, 2019 15:22
@swharden
Copy link
Member

swharden commented Aug 7, 2019

I think the PlotSignalConst name you came up with is very good. It makes it clear that this plot type is optimized for signals with constant data.

I agree with your suggestion that the argument to turn threading on/off needs a better name (which describes its behavior rather than its implementation). This argument controls whether or not to allow the old low-speed rendering while the trees are still being calculated for the new high-speed method. It will rarely be changed, and probably only in console applications. Perhaps:

plt.PlotSignalConst(data, allowEarlyRendering: false);

StendProg pushed a commit to StendProg/ScottPlot that referenced this pull request Mar 16, 2020
PlotSignalConst() - faster rendering for millions of points
swharden added a commit that referenced this pull request May 22, 2020
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

Successfully merging this pull request may close these issues.

3 participants