PDA

View Full Version : OpenGL multi-threaded cpu drainage



ColacX
11-23-2009, 01:43 PM
Hi there.
I have a Rendering thread and a Loader thread.
They share lists

wglShareLists(this->renderingContext, renderingContext2);

Rendering thread loops

while(this->isRunning){
this->draw();
SwapBuffers(window1->getDeviceContext()); //blocking for verticalSync
}

Loader thread loops

while(this->isRunning){
look for jobs
do jobs
delete jobs
Sleep(10000);
}

when loader thread is deactivated the game uses 1% according to windows taskmanager

when loader thread is activated the game uses 60%

this isnt so much of a problem but id like to optimize and im curious of why this is happening.

ZbuffeR
11-23-2009, 04:31 PM
Is there a similar cpu usage with a simple loader thread like this one :

while(this->isRunning){
Sleep(10000);
}

ColacX
11-24-2009, 12:00 AM
Is there a similar cpu usage with a simple loader thread like this one :

while(this->isRunning){
Sleep(10000);
}
yes

mfort
11-24-2009, 09:05 AM
What gfx HW? (NVIDIA?)

Brolingstanz
11-24-2009, 09:29 AM
"Sleep(10000);"

That's one whale of a snooze! (Wake me when it's over. ;-))

ZbuffeR
11-24-2009, 09:42 AM
@Brolingstanz: depends on the unit, what about microseconds ?

Brolingstanz
11-24-2009, 09:48 AM
lol... or light years?

ZbuffeR
11-24-2009, 10:46 AM
C'mon, a light year is a (big) unit of distance, not time :-D


Seriously, what Sleep() is that ? Time units, implementation details ? Does varying the value change the cpu usage, still on the while-isrunning-sleep loop ? (ie. doing 1000, 100 , 10, 100000 ...)

ColacX
11-24-2009, 11:48 AM
C'mon, a light year is a (big) unit of distance, not time :-D


Seriously, what Sleep() is that ? Time units, implementation details ? Does varying the value change the cpu usage, still on the while-isrunning-sleep loop ? (ie. doing 1000, 100 , 10, 100000 ...) Just the standard windows library Sleep(dword miliseconds) anyone else tried this on their computers?


What gfx HW? (NVIDIA?)

And yes NVidia Geforce 9600M GT TurboCache

mfort
11-24-2009, 01:23 PM
try this:

Open NVIDIA Control Panel (RMB on desktop or in Control Panels) Select „Manage 3D settings“, tab „Global Settings“, scroll
down the list and select line „Threaded optimization“, choose Off

ColacX
11-25-2009, 03:40 AM
try this:

Open NVIDIA Control Panel (RMB on desktop or in Control Panels) Select „Manage 3D settings“, tab „Global Settings“, scroll
down the list and select line „Threaded optimization“, choose Off


nope no diffrence
i did try this while i was in there:
i turned off vertical sync and added a Sleep(1000/60) in the rendering thread. cpu usage went down to 2%

ZbuffeR
11-25-2009, 07:26 AM
Do use glFinish() and or glFLush() ?
glFinish on nvidia used busywait last I checked, which means 100%cpu usage.

ColacX
11-29-2009, 05:10 PM
Do use glFinish() and or glFLush() ?
glFinish on nvidia used busywait last I checked, which means 100%cpu usage.
woohoo glFinish() combined with a Sleep(1000/70) did the trick cpu usage drop to 18% while maintaining 60 in fps thanks.

glFlush(); didnt do anything.

woohoo put glFinish on my loader-thread aswell cpu-usage droped to 6% really nice thanks man

In software engineering, busy waiting or spinning is a technique in which a process repeatedly checks to see if a condition is true, (aka cpu waster)

seems to have also fixed another bug where gl display lists wouldnt be compiled or called correctly, although im not sure.

mfort
11-30-2009, 01:29 AM
Your workaround is nice, but it is not a solution.
It works because your scene is simple for your GPU.
When you add more complexity the render time grows.
Then the Sleep value will be too high and fps will drop.

On the other hand there is no real solution until NV improves the driver.

ColacX
11-30-2009, 05:34 AM
Your workaround is nice, but it is not a solution.
It works because your scene is simple for your GPU.
When you add more complexity the render time grows.
Then the Sleep value will be too high and fps will drop.

On the other hand there is no real solution until NV improves the driver.

yeah already noticed that :p but i think i can fix it if i do some fps calcs on the sleeptime

yooyo
11-30-2009, 09:02 AM
Dont count on that... Sleep(N) in windows doesn't mean it will sleep N miliseconds. Depending on hardware, drivers and application timer cofiguration, Sleep(N) works different.
Sleep(1) can sleep 15-16ms, Sleep(16) can sleep 30-32ms...

ColacX
11-30-2009, 11:59 AM
Im satisfied with my answer thanks all.

elFarto
11-30-2009, 12:19 PM
That loader loop is odd. Why are you spinning when you know there's no work todo? Try implementing a loop like this:

while (true)
{
nextJob = getNextJob(); //may block waiting for the next job
do(nextJob);
}
Regards
elFarto

ColacX
12-06-2009, 08:53 AM
That loader loop is odd. Why are you spinning when you know there's no work todo? Try implementing a loop like this:

while (true)
{
nextJob = getNextJob(); //may block waiting for the next job
do(nextJob);
}
Regards
elFarto
was going to switch the sleep for a yield later on

ColacX
12-28-2009, 07:20 PM
i thought up a better way to do the loading.

if i only start the loaderThread when theres work to do and delete the thread when there is no work to do the OpenGL wouldn't have make the costfull switching between the threads. That way for most of the time only the renderingThread would be running.

So I tried this but it didnt work. Once the loaderThread has been started it can also be stopped, but OpenGL doesn't seem to recognise this even though there's is no longer any thread for it to contextswitch too, cpu usage 50% average, ill have to guess i'm missing some kind of OpenGL deloading code.

So my questions is what is the code? I've tested some that didnt work.

Note as before I also tried to never start the loaderThread and let the renderingThread handle all the rendering, cpu usage 6% average.



LoaderThreadStart(){
this->thread = new Thread(this);
}

LoaderThreadStop(){
delete this->thread;
}

LoaderThreadRun(){
if(!wglMakeCurrent( this->window1->getDeviceContext(), this->renderingContext)){
throw "Loader: run: wglMakeCurrent failed\n";
}

this->doJobs();

//jobs are done so this thread can return

//glFinish(); //tested no effect
//wglMakeCurrent(0,0); //tested no effect
//wglDeleteContext(this->renderingContext); //tested no effect
}

ColacX
12-29-2009, 06:47 PM
Just to specify the problem more clearly

renderingThread started
number of openGL threads: 1, cpu-usage: 6%
loadingThread started
number of openGL threads: 2, cpu-usage: 50%
loadingThread finished work, deleting loadingThread
number of openGL threads: 1, cpu-usage: 50% ???? wtf?