1 Attachment(s)
Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Dear UWE,
I'm testing QwtPlotCurve with "big data". Previously you said that in QWT SVN trunk there is QWT 6.2 where I can find QwtPlotCurve::FilterPointsAggressive to increase perfomance of plotting large data. So I use QWT 6.2 from SVN.
I plotted curves in cycle up to 20000 and each curve has 1000 points. Plotted data takes about 300 megabytes RAM and takes to plot maybe 25 seconds (I didn't measure exactly but not bad as few second is spent for reading data from SSD disk).
When I tried to add QwtPlotCurve::setPaintAttribute I didn't see any changes in perfomance. I tried to set MinimizeMemory/FilterPoints/FilterPointsAgressive to true/false with no luck. Maybe I do something wrong? Here is the code:
Code:
for (quint64 j = 0; j < nTrc; j++){
curve->setPen( Qt::blue, 1 );
curve
->setRenderHint
( QwtPlotItem::RenderAntialiased,
true );
curve->setOrientation(Qt::Vertical);
curve->setSamples(Col<float>(TRACE_DATA.col(j)+j).memptr(), t.memptr(), nSamp); // data from Armadillo matrix
curve
->setPaintAttribute
(QwtPlotCurve::MinimizeMemory,
true);
// I tried to swap true/false everywhere... curve
->setPaintAttribute
(QwtPlotCurve::FilterPointsAggressive,
true);
curve->attach( plotForm );
}
Woud it help if I set curve->setRenderThreadCount(N); in my case (for hundreds and thousands curves)?
Here is how it looks for 50 lines (I tried it up to 20000 lines):
Attachment 13357
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Antialisasing is a substantial performance killer and does not make much sense in your case - so the first thing you should do is to turn it of. Using a pen width > 1 is another well known problem - one that is not used in your code.
A general way to improve rendering is to use a hardware accelerated paint engine. On Unix systems this is pretty easy by using the X11 paint engine, that is available in Qt4 or Qt >= 5.10. Unfortunately Qt development decided to make the slow software renderer being the default even on X11 systems, where you have a much better option. On Windows you have to use an OpenGL canvas - or at least have to use the QwtPlotCanvas::OpenGLBuffer option you can find in SVN trunk.
The FilterPointsAgressive/FilterPoints flags make use of the fact, that when rendering a curve with many points many of them will end up at the same position as others. But for a plot with many curves of a limited number of points these flags won't help much.
Enabling the MinimizeMemory flag is counterproductive in terms of performance and is of no value when having curves with only 1000 points.
Uwe
1 Attachment(s)
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Uwe,
I'm trying to explore QwtPlotOpenGLCanvas. I successfully built QWT 6.3.0 from SVN trunk.
I found your discussion about perfomance and OpenGL issues: https://www.qtcentre.org/threads/666...ming-is-*SLOW*
Now I can run your code from there. But when I change canvas to QwtPlotOpenGLCanvas *canvas = new QwtPlotOpenGLCanvas(); my launched application looks like green window (black or yellow on the picture) without curves. And there is a warning:
DXGI WARNING: IDXGIFactory::CreateSwapChain: Blt-model swap effects (DXGI_SWAP_EFFECT_DISCARD and DXGI_SWAP_EFFECT_SEQUENTIAL) are legacy swap effects that are predominantly superceded by their flip-model counterparts (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL and DXGI_SWAP_EFFECT_FLIP_DISCARD). Please consider updating your application to leverage flip-model swap effects to benefit from modern presentation enhancements. More information is available at http://aka.ms/dxgiflipmodel. [ MISCELLANEOUS WARNING #294: ]
QSize(600, 400) 0
Since I'm not quite familiar with graphics and OpenGL it is difficult to understand what is blamed for this app behaviour.
If you know something that possibly could help with that please give me a hint.
I'm on Windows 10 x64, DirectX 12, Qt 5.14.1, compilator MSVC 2017 x64.
Here is the code that I use:
Code:
#include <QApplication>
#include <QElapsedTimer>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_opengl_canvas.h>
#include <QtMath>
#include <QDebug>
#include <QtOpenGL>
{
public:
MyPlot()
{
const int numPoints = 10;
//QwtPlotCanvas* canvas = new QwtPlotCanvas();
QwtPlotOpenGLCanvas *canvas = new QwtPlotOpenGLCanvas(); // NEW OpenGL Canvas
#if 0
#endif
setCanvas( canvas );
setCanvasBackground( Qt::white );
setAxisScale
( QwtPlot::yLeft,
-1.5,
1.5 );
setAxisScale
( QwtPlot::xBottom,
0.0, numPoints
);
curve->setTitle( "Some Points" );
curve
->setPaintAttribute
(QwtPlotCurve::FilterPointsAggressive,
true);
for ( int i = 0; i < numPoints; i++ )
curve->setSamples( points );
curve->attach( this );
}
virtual void drawCanvas
( QPainter *painter
) {
QElapsedTimer timer;
timer.start();
qDebug() << size() << timer.elapsed();
}
};
int main( int argc, char **argv )
{
MyPlot plot;
plot.resize( 600, 400 );
plot.show();
return a.exec();
}
Attachment 13362
1 Attachment(s)
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Oh! Since I'm on the laptop I have two video cards: one is Intel (integrated and used most of the time by default but it is slow) and NVidea (additional, more powerful).
So before that my application used to launch with integrated slow Intel video card but to run OpenGL I need NVidea. In NVidea contol panel I added my application and chosed NVidea videocard for this application.
Now it looks good, I'm going to test qwt opengl for my issues :)
Attachment 13363
2 Attachment(s)
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Uwe,
I tested QwtPlotCanvas::OpenGLBuffer and for my task I don't any difference in perfomance wether I use canvas->setPaintAttribute( QwtPlotCanvas::OpenGLBuffer, true); or canvas->setPaintAttribute( QwtPlotCanvas::OpenGLBuffer, false );. Both of them takes about 20 seconds to plot 20000 curves each of 1000 points.
I use the following settings:
canvas->setPaintAttribute( QwtPlotCanvas::OpenGLBuffer, true ); // change from true to false
curve->setPaintAttribute(QwtPlotCurve::MinimizeMemory, false);
curve->setPaintAttribute(QwtPlotCurve::FilterPoints, false);
curve->setPaintAttribute(QwtPlotCurve::FilterPointsAggre ssive, false);
What do you think?
I also tried to use QwtPlotOpenGLCanvas but I cannot handle zooming to work. No panning, no zooming:)
But there is a maybe a bug in QwtPlotCanvas::OpenGLBuffer(true) when I need to fill the area between baseline and curve. In the pictures attached I demostrate that.
By the way, QwtPlotOpenGLCanvas fills this area finely
Attachment 13364
Attachment 13365
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
You will never ever have a good performance with a plot of 20000 curves * 1000 points and to me it sound like you are taking the wrong approach.
Are you sure, that your data is not more like something you would display as raster data.
Uwe
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Uwe,
Yes 20000 curves it is too much but I'm exploring QWT and after that I should decide how to design the application.
There is a small free software that can plot more curves with quite good perfomance SEISEE https://mail.dmng.ru/freeware/?lang=en
I can't understand how it works but if you are interested to test it I could find some data to use in SEISEE
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
In the end you have to understand what is going on. A curve usually ends up at QPainter::drawPolyline, Qwt can do a couple of optimizations, but that's it.
For one curve with many points optimzations will be more successful, but for many curves with a limited number of points there is not that much that can be done.
Maybe one optimzation, that comes to my mind is disabling autoscaling, so that the bounding rectangle of the curves has not to be done by iterating over all curves. But this has to be done only once.
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Thank you Uwe
Even I started with C/C++ few month ago I feel that I'm starting to understand the philosophy of QWT. I still have some difficulties but it needs some time to understand.
I already disabled autoscaling.
Actually I think that QWT is fast enough to fit my needs.
At least as I'm using Armadillo library I'm able to perform 2D interpolation before plotting in case when number of curves and number of of points in each curve significantly exceed heigh and width of canvas in pixels.
Thank you!
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Quote:
Originally Posted by
Vasya
At least as I'm using Armadillo library I'm able to perform 2D interpolation before plotting in case when number of curves and number of of points in each curve significantly exceed heigh and width of canvas in pixels.
Guess by interpolation you mean clipping the curves against the canvas boundaries. This is done by default ( QwtPlotCurve::ClipPolygons ) and doing it in advance does only make sense, when you do not have to deal with operations like zooming. There is also an implementation of Douglas Peucker available ( https://qwt.sourceforge.io/class_qwt...ve_fitter.html ), but as this is an expensive algo it should be done in advance - only passing the reduced number of points.
Uwe
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
I think I'm talking about something different.
My plotted curves have some specific features. They are like deviation from some vertical baseline (and each curve has a baseline).
Lets suppose that canvas width is 500 pixels. Every curve has QPen width equal to 1 and if all curves are settled equidistantly on the canvas then there is no much sense to plot more than 500 my "pseudovertical" curves.
So if I try to plot 5000 curves then I can choose every tenth (0, 10, 20, ...) curve and then plot it.
And the same for Y axis. Every point of every of my curves is settled equidistantly (Y axis of every point is something like : 0, 2, 4, 6, 8 ...). So linear interpolation is fast and could improve plot perfomance when number of points much bigger than canvas height
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Quote:
Originally Posted by
Vasya
Every curve has QPen width equal to 1 and if all curves are settled equidistantly on the canvas then there is no much sense to plot more than 500 my "pseudovertical" curves.
So if I try to plot 5000 curves then I can choose every tenth (0, 10, 20, ...) curve and then plot it.
Not sure if this is a type of optimization, that is common of enough to explicitely support it in Qwt - curve points are usually not only shifted by the distance of the baselines. But nobody prevents you from doing so - simply hide/show curves depending on scale ranges.
Quote:
Originally Posted by
Vasya
Every point of every of my curves is settled equidistantly (Y axis of every point is something like : 0, 2, 4, 6, 8 ...). So linear interpolation is fast and could improve plot perfomance when number of points much bigger than canvas height
Being equidistant does not make anything faster and I'm not sure what you mean by "interpolation" here. But clipping ( skipping points being outside the canvas ) and making use of the fact, that you can unite points, that are mapped to the same position, when drawing to an integer coordinate based paint device ( screen ) can have an significant effect. But the second ( = QwtPlotCurve::FilterPointsAggressive ) optimization won't be very effective, when you only have 1000 points. Drawing 1000 points to a canvas having a height of 1000 pixels does not reduce the number of points significantly.
Uwe
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Quote:
Originally Posted by
Uwe
Not sure if this is a type of optimization, that is common of enough to explicitely support it in Qwt - curve points are usually not only shifted by the distance of the baselines. But nobody prevents you from doing so - simply hide/show curves depending on scale ranges.
Yes thank you for the hint, I'm going to try to make optimization based on the show/hide (curve->setEnabled(true/false)) properties. That should not be much difficult.
About vertical resolution:
Probably that is not so necessary but depending on plotted data each curve may have up to 5000 points (usually it is 2000-5000 points but may vary). In this case QwtPlotCurve::FilterPointsAggressive may be useful I think (or at least it should not consume much time to execute if number of points is small, less than 1000, I'm going to test it).
And what about vertical linear interpolation:
I think in this case interpolation for curves that reduces the number of plotted points is inapropriate, sorry for confusing you. But sometime ago I found this algo in Matlab: https://www.mathworks.com/matlabcent...40790-plot-big
But that time I needed something like that to plot 2D data (spectrogram) with the same 1000 by 20000 points (or more) in each direction (the data is the same as for my curves but plotted NOT as curves but as spectrogram). And I wrote matlab code that choses points in X and Y direction before plotting Z data. I think in QWT spectrogram with big data could be useful also. Maybe FilterPointsAggressive could find some application at spectrogram?
This is just an idea wich came to my mind now but probably QWT already has something similar (I didn't work with QWT spectrogram yet but I'm going to).
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Quote:
Originally Posted by
Vasya
I think in QWT spectrogram with big data could be useful also.
The impact of the data size depends on the type of resampling being used - for example with nearest neighbor ( = default ) the performance does not depend on the data size.
But the opposite is true: when the resolution of the data is smaller, than the one on screen rendering will be faster as in situations, where you have to calculate all pixels.
Quote:
Originally Posted by
Vasya
Probably that is not so necessary but depending on plotted data each curve may have up to 5000 points (usually it is 2000-5000 points but may vary). In this case QwtPlotCurve::FilterPointsAggressive may be useful I think (or at least it should not consume much time to execute if number of points is small, less than 1000, I'm going to test it).
The algo calculates 4 points for each pixel: enter, min, max, leave. So when having 5K points and 1K pixels you will have almost no effect in reducing the number of lines to be painted.
But the algo is fast and should not hurt that much.
HTH,
Uwe
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
I think I misunderstood something but this interesting to know
Quote:
Originally Posted by
Uwe
The impact of the data size depends on the type of resampling being used - for example with nearest neighbor ( = default ) the performance does not depend on the data size.
Does this only concernes to the situation when number of pixels is more than number of data points (say canvas size = [500, 500] and data size = [100, 100])? In this case we have to apply nearest neighbor interpolation to resize our data from [100, 100] to [500, 500] does it correct?
And the opposite, when canvas size [500, 500] and the data is [5000, 5000]. In this case we can only plot 10% of our data. I don't know wether such software like QWT does the resampling of our data before plotting or it shows all the 5000*5000 points on the 500*500 screen?
I've always been interesting about that beacause in Matlab my nearest-neighbor resampling improoved the plotting perfomance compared to plotting raw data.
In Matlab I was using this function after I resample the data: https://www.mathworks.com/help/matlab/ref/imagesc.html
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Quote:
Does this only concernes to the situation when number of pixels is more than number of data points (say canvas size = [500, 500] and data size = [100, 100])? In this case we have to apply nearest neighbor interpolation to resize our data from [100, 100] to [500, 500] does it correct?
In case of nearest neighbor Qwt would create a 100x100 image - scaling to the paint device resolution will happen later. Resizing the data is not necessary for no type of interpolation.
Quote:
And the opposite, when canvas size [500, 500] and the data is [5000, 5000]. In this case we can only plot 10% of our data. I don't know wether such software like QWT does the resampling of our data before plotting or it shows all the 5000*5000 points on the 500*500 screen?
The application has full control over the resampling. Note, that there is a class specifically supporting data being stored as a 2x2 array ( https://qwt.sourceforge.io/class_qwt...ster_data.html ), but in general the data can be hold in any way. See the spectrogram example, that does not even store the data at all.
Quote:
I've always been interesting about that beacause in Matlab my nearest-neighbor resampling improoved the plotting perfomance compared to plotting raw data.
QwtPlotSpectrogram does not iterate over the data - it iterates over the pixels of the image and for nearest neighbor it picks the corresponding values.
When shrinking the size of the data below the resolution of the screen you will have an effect on the performance as Qwt would not create an image in a resolution, where no corresponding data exists and less pixels need to be calculated. Otherwise your type of resampling would have no effect on the performance - see above.
You can enable DEBUG_RENDER in qwt_plot_spectrogram.cpp and do some tests with the spectrogram example. Actually the performance of plotting will heaviliy depend on your implementation of QwtPlotRasterData::value(). This one is called for every pixel of the resulting image ( this is the resampling ) and having expensive calculations there will slow down rendering.
Uwe
Re: Check perfomance of QwtPlotCurve with setPaintAttribute for displaying large data
Thank you for explanation. I need to practice it more and less question I will have.