Performance issue with multiple rendering threads- Plzz Help

In my process, I can have up to eight rendering threads drawing graphics to eight windows. The blocking mechanism in these threads are call to SwapBuffers() and a Sleep of 100 ms. The process, when it starts, has 7 rendering threads drawing graphics to seven windows. But the moment I create the 8th rendering thread, the process starts consuming nearly 90% of the CPU. I found that the new rendering thread, which I had created, consumes most of the CPU. I tried increasing the Sleep interval, but it has no effect.

I have lots of other threads already running in system along with this process. They consume nearly 70% of the CPU. This means only 30% of the CPU is left for rendering threads.

My PC config: Pentium4-2 Ghz, Win2K and Nvidia Geforce4 Ti600 graphics card.

Thanks,
Prabhu.

I think your blocking mechanism isn’t robust enough. Just calling Sleep() doesn’t really help because it’s almost impossible to predict how long to sleep for at any one time - esp. with 8 threads.

Are you rendering to a single RC or have you created multiple OpenGL contexts? If you have a single HGLRC and just need to serialise access from your 8 threads, it’s better to use a CriticalSection() to handle thread synchronisation. Then you will benefit whenever any OpenGL oepration takes less than your pre-defined 100ms. This will prevent thrashing - which is what I suspect you are seeing now.

I created multiple OpenGL contexts. I also use a critical section for the swapbuffer call.

You may do better with a single OpenGL context. Protect all gl calls with a critical section, use wglMakeCurrent() to select which of your 8 DC’s you need during each thread’s rendering loop and get rid of your Sleep() call.

Switching OpenGL contexts is expensive - this may have an effect on your problem. Is it possible for you to try the above and see if this helps?

Hi Rog,

Thanks for your response.
It could be a big change to my S/W. But it is definitely worth trying because I found this process is always taking 90% of the CPU with low-end cards like Geforce4 MX 440 and Geforce2MX 200.

I would like you to know that I had added 330 threads to my system. So, too many context switches are happening already, and they are consuming lots of CPU. These 330 threads are not part of my graphics process, but they have to be there when the graphics process is executing. Hoping that introducing the OpenGL context switching would not turn out to be too expensive.

Also, this issue is happening only in few PCs with Geforce4 Ti 4600 card. The strange thing is, this issue is not happening in PCs with GeForce FX 5600 card.

Thanks,
Prabhu

I tried as you mentioned. I still found the newly created thread thrashing the CPU.

I have a configuration using which I created 100 non-graphics threads instead of 330 non-graphics threads. This configuration along with the graphics process used to take 30% of the CPU before, but after making the change you mentioned, the utilization came down to 2%!!!

Do you think that extra 230 threads are creating the problem???

Originally posted by prabuva:
[b]… This configuration along with the graphics process used to take 30% of the CPU before, but after making the change you mentioned, the utilization came down to 2%!!!

Do you think that extra 230 threads are creating the problem???[/b]

It certainly looks suspicious!

What the heck do all these threads do? Are they all using synchronisation? You’re not doing the old Sleep() trick with these are you?

I have to say that it’s probably more usual to keep all the graphics stuff in one thread. I don’t know if your application lends itself to this easily or not but that might be worth investigating. Having said that, I don’t think it’s the rendering threads that are causing the problem here. It’s more than likely the other two or three hundred…

[This message has been edited by Rog (edited 11-18-2003).]

No, those threads are not doing any sleep. They are periodic threads, and they will get suspended after they are done with their task in a period. They will get resumed in the next period .

Protect all gl calls with a critical section

I fail to see why that’s neccessary if your code is protected from the makecurrent to the makecurrent(null).

I removed the graphics portion of the process and executed it along with those 330 threads. Then I launched another process, which renders the OpenGL graphics using single thread. It took almost 90% of the CPU!!!
If I run this process in absence of those 330 threads then it is fine. It took hardly less than 2% of CPU.

You could be correct. The other 330 threads are having indirect effect on the rendering threads.

But, I still don’t understand…. why it is not in all PCs having the same GeForce Ti600 card???
I tried in a dual processor PC and another PC with same graphics card. This problem does not exist!!!

Is the OS settings / configuration causing the problem???


I fail to see why that’s neccessary if your code is protected from the makecurrent to the makecurrent(null).

Yes, if the code is protected using makecurrent(NULL) then OpenGL32.dll would ignore the OpenGL API calls made by the code.

Originally posted by prabuva:
[b]I removed the graphics portion of the process and executed it along with those 330 threads. Then I launched another process, which renders the OpenGL graphics using single thread. It took almost 90% of the CPU!!!
If I run this process in absence of those 330 threads then it is fine. It took hardly less than 2% of CPU.

You could be correct. The other 330 threads are having indirect effect on the rendering threads.

But, I still don’t understand…. why it is not in all PCs having the same GeForce Ti600 card???
I tried in a dual processor PC and another PC with same graphics card. This problem does not exist!!!

Is the OS settings / configuration causing the problem???

[/b]

Unfortunately there might be such effects.
I noticed in an older topic that my program refresh the screen asyncronous only when it’s playing some sound also…
I thougth I made something wrong, but when I turned the sound off AND play the sound from an another process (WinAMP) I had the same effect…

[This message has been edited by Csiki (edited 11-19-2003).]

Yes, if the code is protected using makecurrent(NULL) then OpenGL32.dll would ignore the OpenGL API calls made by the code.

No, that’s not what I meant by protection - I mean if you enter a critical section before you makecurrent, and leave the critical section after you makecurrent(null) then there is no need to protect every single gl call. You would need to use this protection when sharing a context, otherwise how the hell is one thread supposed to draw anything correctly if another thread is changing render states?
thread1 : glEnable(GL_LIGHTING)
thread2 : glDisable(GL_LIGHTING)
thread1 : glDrawMyLovelySmoothNormalsSphere()
Like a scene from Duck Soup.

Originally posted by knackered:
[QUOTE]No, that’s not what I meant by protection - I mean if you enter a critical section before you makecurrent, and leave the critical section after you makecurrent(null) then there is no need to protect every single gl call.

Yes that’s actually what I meant when I said “protect all gl calls”. I assumed they would all be within a protected section, not individually protected - that would not only be disatrous, it wouldn’t work.

Sorry for the confusion…

[This message has been edited by Rog (edited 11-19-2003).]

I tried by protecting the bunch of GL calls between each Swapbuffers. Not the individual GL calls. So, it worked!!

It was not like the scene from Duck soup.