PDA

View Full Version : High CPU Usage in Drawing



lordhippo
21st May 2010, 09:37
Hi

at first please forgive me because of my poor English !

i am beginner in qt . i have to make a program to get some data from network and draw it in real time (about 1000 line in second)
but i have a problem. although i use QGLWidget my cpu usage always is too high for drawing these lines (above 60 percent)
my program add these point to a polyline of a pixmap and every 10 msec draw the hole pixmap in QGLWidget

what should i do to decrease CPU usage ??

Thanks

wysota
21st May 2010, 09:46
Decrease the interval at which you are drawing. It is very unlikely your monitor has a refresh rate of 100Hz anyway so there is no point in drawing so often. If that doesn't help, show us some code, we're not trueseers.

SixDegrees
21st May 2010, 09:48
Why is 60% too high? I want my CPU working as hard as it can, all the time, to accomplish whatever task is at hand - ideally, I ought to see it at 100% whenever it's performing a job.

It sounds possible, however, that your approach may not be as efficient as it could be if you are redrawing the entire polyline each time a single point is added. Consider restricting redisplay operations only to the region affected by each point addition, rather than re-rendering the entire image.

lordhippo
21st May 2010, 13:08
thanks for your quick reply

i cant just draw new points because one of the axis of my plotter is for time and the graph should move each time a new data received .
although the high cpu usage is good but what does the GPU do in this example , i have enough job for my cpu to do in this application for example calculate something and report the log in real-time , for this reason i want to decrease cpu usage as less as possible.
here is some of my code :

void Plotter::paintEvent(QPaintEvent * /* event */)
{
QStylePainter painter(this);
painter.drawPixmap(0, 0, pixmap);
painter.end();
}

void Plotter::refreshPixmap()
{
pixmap = QPixmap(size());
pixmap.fill(this, 0, 0);
QPainter painter(&pixmap);
painter.initFrom(this);
drawCurves(&painter);
}

void Plotter::drawCurves(QPainter *painter)
{
QPolygonF polyline(800);

for (int j =data.count-800 ; j < data.count() ; ++j)
{
double x = j/100.0 ;
double y = data[j] ;
polyline[j] = QPointF(x, y);
painter->drawPolyline(polyline);
}
}


i call refreshPixmap() every 10 msec . polyline in drawCurve is temporary and it is just for drawing . my widget is QGLWidget .
i hope anyone can help me to do my job faster.

thank you.

wysota
21st May 2010, 15:00
The least you can do is remove the calculation of the whole polyline each time you update the pixmap. It is likely that all you are doing is adding the points and possibly moving them in some direction. But I'd still say you don't have to recreate the whole pixmap every time. And I really suggest you reduce the timer interval to say... 50ms. It still gives you 20 fps which is surely more than enough for real time data update.

high_flyer
21st May 2010, 16:46
Why is 60% too high? I want my CPU working as hard as it can, all the time, to accomplish whatever task is at hand - ideally, I ought to see it at 100% whenever it's performing a job.
This makes no sense!

Having your CPU work in 100% says nothing about the efficiency of its usage!
It only means it is very busy.
The CPU can be 100% in usage, while doing nothing more then some repetitive empty task.

Modern CPU's, are so fast, and have so many "secondary" processors and other mechanisms that release it of much work, that any reasonable application, should not add more then few percent of usage if any.

In general applications should be designed to use as little resources as possible, starting with the CPU.

There are some applications that need to kranch a lot of data, in such applications, it is acceptable if the CPU is used more, but even in such applications, no, specially with such applications, it is important to calculate the expected CPU usage, and see to it that the implementation is not over it, and developers of such application very often invest a lot of thinking in implementation optimization so that less as possible CPU will be used, resulting in faster execution.
This is by the way, why the GPU's came to be so powerful, if you would try to run modern games only on the CPU, you would see one frame per few seconds at best, and the CPU would run 100% all the time.
More an more applications which have to do a lot of data manipulation and calculation are moving that part to the GPU (which is known as general purpose GPU programming), leaving the CPU only with the relatively cheap tasks, such as GUI ect.

wysota
21st May 2010, 17:00
If I have a processor with scalable work frequency, then "100%" in lowest state is something much different than "100%" in the highest state. In my opinion operating in arbitrary percentages in contidions that can't be reproduced yields no scientific value. Just as checking memory usage through the task manager :)

lordhippo
21st May 2010, 17:03
i change the interval to 50 msec then CPU usage decrease to 25 percent !
i am now working on do something to avoid repaint all of pixmap every 50 msec .

now my question is 25 percent just for drawing 800 line is not too high although i use opengl widget ?
my program is not too efficient or its is common usage for this job .

another interesting result is happens . when i change my widget from QGLWidget to QWidget and re run the program the result do not change and CPU usage is also about 25. i am sure that this usage is just for drawing because when i comment the line of drawing pixmap the usage then decrease to 3 percent.

are you sure that Qt doing something extra about using GPU in use of QGLWidget ?

wysota
21st May 2010, 17:24
You are drawing a pixmap, not 800 lines. And if you do that through OpenGL then it's the GPU that does that and not the CPU. The latter is busy recalculating your polyline :) And please don't measure CPU usage in percentages ;)

SixDegrees
21st May 2010, 18:39
In general applications should be designed to use as little resources as possible, starting with the CPU.


Nonetheless, when there is work to be done, I don't was a slacker CPU that's only giving me 60%, or anything less than 100%, of its capability.

What really needs to be measured here is performance - is the drawing taking place quickly enough, with "enough" defined to match application requirements. Or, whether or not the entire system is bogging down during drawing, which doesn't seem to be the case.

As others have already noted, desktop tools are pretty much useless for measuring things like this. On Unix, anyway, there are command line tools and system calls that will report CPU usage over a given timespan; whether there are similar tools in a Windows environment, I don't know, but I imagine there must be.

squidge
21st May 2010, 19:06
i change the interval to 50 msec then CPU usage decrease to 25 percent !
i am now working on do something to avoid repaint all of pixmap every 50 msec .

now my question is 25 percent just for drawing 800 line is not too high although i use opengl widget ?Doesn't that depend on the processor, what other applications are running, and lots of other things?

If your processor is a 386DX-33, then 25% for your drawing is quite acceptable. If it's a Core i7 975, then 25% is 100% CPU usage of a single core, so it's awful.


Nonetheless, when there is work to be done, I don't was a slacker CPU that's only giving me 60%, or anything less than 100%, of its capability.The only processors that do give you 60% is mobile versions that care about battery life. You have to select whether you want maximum performance or maximum battery life, or let the system decide depending on load over a given time period. Desktop processor typically always run at 100%, the figure is an estimation of what the running processes are currently using in a given time frame. If there is no work to be done (for example, all processes are waiting for timers to expire, I/O, or things like that), the processor might as well be asleep, so it will do so.

lordhippo
21st May 2010, 21:54
hi again

my computer is a Sony Vaio Z laptop with core2 Duo 2.66 cpu and 4GB Ram.
after wysota post the previous reply i write a program to tell him that my question is about the true trues.

here is a very very simple program for test , it just refresh a pixmap without any change in screen .
my result is when i use QGLWidget : 8-10% cpu usage and when use QWidget about 45-50% just for this program.
there is some mistake in my program or it is common !

thanks for your attention

squidge
21st May 2010, 22:38
A Core2 Duo is a dual-core processor, so 50% is an entire core doing nothing but your application. If you put your application on a single core machine, it would use up 100% CPU, constantly.

You do understand that the 'update' method causes the widget to repaint, and your using it in your repaint function, so the repaint never finishes, right?

lordhippo
21st May 2010, 23:04
yes
you right . i comment the update function and call it from a timer time-out function and its just working properly , but when i decrease the timer interval lower than 20 msec the cpu usage go up to 25%.
it is for overlapping the function call ?
do you know how many time the paintEvent function calls in a second ?

thank you very very much for your help

wysota
21st May 2010, 23:45
my computer is a Sony Vaio Z laptop with core2 Duo 2.66 cpu and 4GB Ram.
after wysota post the previous reply i write a program to tell him that my question is about the true trues.

here is a very very simple program for test , it just refresh a pixmap without any change in screen .
my result is when i use QGLWidget : 8-10% cpu usage and when use QWidget about 45-50% just for this program.
there is some mistake in my program or it is common !

If you want to make a test that has any reliablility, you need to call the function under test few thousand times and measure the total time used by the process (it's not the same as real time elapsing between start and end of the measurement) and then divide it by the number of iterations to know how much time it takes to process the function. For instance to measure time used by the process you can use time(1) on Linux or clock(3) or QBENCHMARK macro from QTestLib regardless of the platform (just use a proper backend).

squidge
21st May 2010, 23:48
It will be called whenever it needs to be called - eg. if another window is obscurring it, and then moves away, or when you call the update method. It's not a specific number of times per second.

I don't know why you need to repaint the window 50 times a second either? (1000/20 = 50).