By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,084 Members | 1,233 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,084 IT Pros & Developers. It's quick & easy.

Time critical thread seems to pause briefly once every few seconds

P: n/a
I have an application in which there exist a thread that handles directx
rendering. It runs on a dual core system with windows vista and xp.
It is set to have highest priority and simply loops with
while(isRendering)
{
prepare for rendering;
do render;
present()
}

It runs smoothly and then pauses very briefly and resumes.
I assume it has to do with windows wanting to do some background processing,
but I did not expect it to interrupt a high priority thread.
I am wondering if it has to do with the call to directx's present. It will
not always return immideately. Sometimes, when it has filled an outbuffer
with rendered frames (that buffer is small.. 2 or 3 frames), it will block.
If the thread blocks there then it will become idle and windows will grab
its processor for its own purposes and not release it again quickly enough.
This then causes the small pause in a high priority thread?

Generally with two cores and few processes, I beleive the core running the
critical thread will be more or less reserved for the thread and the other
core will be uses for low priority work. Is this not correct?

I am running low on ideas to how I should fix this, but it would help to
hear if my theory seem plausible at all. If it is, would the solution then
be to do a spin wait in the thread when I can see that present() will block?
Something like replacing present() with
while(presentWillBlock());
present();

This way the thread never powers down and should not worry about anyone
taking its core?

Jan 9 '08 #1
Share this Question
Share on Google+
8 Replies


P: n/a
On Wed, 09 Jan 2008 01:13:46 -0800, Joe Withawk <no@no.nowrote:
I have an application in which there exist a thread that handles directx
rendering. It runs on a dual core system with windows vista and xp.
It is set to have highest priority and simply loops with
while(isRendering)
{
prepare for rendering;
do render;
present()
}

[...]
Generally with two cores and few processes, I beleive the core running
the critical thread will be more or less reserved for the thread and the
other core will be uses for low priority work. Is this not correct?
That assumes that your thread is the only high priority thread on the
computer. If there are enough high priority threads, they will all
consume the available CPU cores and no lower priority thread will get to
run (mostly).

Philosophically, I wouldn't call a rendering thread "time critical".
"Time critical" is for things that, if you do not process them by some
specific time something simply fails. Examples of this would be a thread
servicing an unbuffered i/o port (or one with a very small buffer), such
as reading from some kind of serial port, or writing data to an audio
output device.

Even for a "time critical" thread, raising the priority is only
appropriate if you know that the thread _must_ run when it's time for it
to run, but it will finish quickly, never consuming its entire timeslice.

A rendering thread doesn't fall into that category.

It's difficult to say without having code to test, but...if I had to
guess, I'd guess that your pausing is _because_ your thread has elevated
priority. This isn't an appropriate approach anyway, but in this case I
suspect that you are starving lower priority threads. But Windows doesn't
let threads get completely starved. Eventually, they get a temporary
priority boost until they're high enough to run.

At that point, a whole bunch of threads that have been starved for
attention then get to do whatever it was that they wanted to do, and your
high-priority thread gets to wait for them.

This will probably sound counter-intuitive, but the solution to your
problem is likely to be to stop messing with the thread priority and leave
your thread at normal priority. Or even to _lower_ the thread priority a
bit. Lowering the priority, your thread will still get practically as
much CPU time that it otherwise would have gotten, but the system will be
much more user-responsive. It's a much more user-friendly way to write
your code.

Bottom line: threads that don't block shouldn't be set to an elevated
priority. If anything, they should have _lowered_ priority.

Pete
Jan 9 '08 #2

P: n/a
Even for a "time critical" thread, raising the priority is only
appropriate if you know that the thread _must_ run when it's time for it
to run, but it will finish quickly, never consuming its entire timeslice.

A rendering thread doesn't fall into that category.
Mine does actually. I need to feed an external dvi to svideo-converter, and
if I fail then the odd even scanlines will come out of sync and all hell
breaks lose. Especially since I have no feedback telling me exactly how much
I am behind so I can compensate.
It's difficult to say without having code to test, but...if I had to
guess, I'd guess that your pausing is _because_ your thread has elevated
priority. This isn't an appropriate approach anyway, but in this case I
suspect that you are starving lower priority threads. But Windows doesn't
let threads get completely starved. Eventually, they get a temporary
priority boost until they're high enough to run.
Yes I saw thatsuggestion in theother thread I started about fiding a
profiler to tell me exactly what is going on. It is a good one too, but I
tried lowering priority and the problem actually got worse :-/
Bottom line: threads that don't block shouldn't be set to an elevated
priority. If anything, they should have _lowered_ priority.
There are many details let out in my posts, for obvious reasons, but my
thread do actually block.
It renders at most 3 frames ahead and then blocks until the graphics card
pushes out a frame and then it writes yet another frame.
That is also why it seems odd that I see the pause. 3 frames with 60Hz is
50ms which seem like a very long time to be preempted.

Jan 9 '08 #3

P: n/a
On Wed, 09 Jan 2008 12:40:37 -0800, Joe Withawk <no@no.nowrote:
[...]
There are many details let out in my posts, for obvious reasons, but my
thread do actually block.
It renders at most 3 frames ahead and then blocks until the graphics
card pushes out a frame and then it writes yet another frame.
That is also why it seems odd that I see the pause. 3 frames with 60Hz
is 50ms which seem like a very long time to be preempted.
Well, I don't really understand the nature of the problem you're trying to
solve. However, I'd suggest that if the problem is that you can't risk
having pairs of frames disconnected, then perhaps rendering three frames
at a time isn't a good idea. It would probably be better to render pairs
of frames at a time, yielding in between so that other threads get a
chance to run and are less likely to preempt you when you're trying to do
something.

Pete
Jan 9 '08 #4

P: n/a
Well, I don't really understand the nature of the problem you're trying to
solve. However, I'd suggest that if the problem is that you can't risk
having pairs of frames disconnected, then perhaps rendering three frames
at a time isn't a good idea. It would probably be better to render pairs
of frames at a time, yielding in between so that other threads get a
chance to run and are less likely to preempt you when you're trying to do
something.
That was not a bad suggestion actually.
Not that it would solve the problem of having the odd/even get crossed, but
it might be a goog idea to actively relinguish control when I know it is ok.
Well.. if I am sure to get it back again within 50ms that is. I will try it.
The reason it doesnt really help to render two frames and then wait is that
if I lose one frame (or rather field) in between paits of two fields, then I
still get out of synch.
I will try actively releasing. I assume this is best done with
Thread.Sleep()?

Jan 10 '08 #5

P: n/a
On Thu, 10 Jan 2008 11:33:55 -0800, Joe Withawk <no@no.nowrote:
[...]
The reason it doesnt really help to render two frames and then wait is
that if I lose one frame (or rather field) in between paits of two
fields, then I still get out of synch.
If you're only drawing two fields, I don't see how you could lose a third
one "in between pairs of two fields". But, whatever.
I will try actively releasing. I assume this is best done with
Thread.Sleep()?
Yes. Call Thread.Sleep(1) (if you pass 0, you will only yield to threads
of the same or higher priority...passing 1 ensures that all runnable
threads will get a chance to execute).

Pete
Jan 10 '08 #6

P: n/a
Yes. Call Thread.Sleep(1) (if you pass 0, you will only yield to threads
of the same or higher priority...passing 1 ensures that all runnable
threads will get a chance to execute).
Did not do the trick though. :-/

Perhaps this whole question should be refhrased to...
on an otherwise clean installation og windows vista on a system with a core
2 duo 1.5GHz, should I not could expect to never get preempted for as long
as 50ms? Should I not could expect to run more often than this? Should I
conclude that the system is faulty and that the application itself is not to
blame?

Jan 10 '08 #7

P: n/a
On Thu, 10 Jan 2008 14:27:11 -0800, Joe Withawk <no@no.nowrote:
If I need to do something every 16 ms and I am preempted for longer than
that, then the problem is right there. Is there something I don't see
here?
I don't know. I may have misunderstood your statement. But it seems to
me that if your code can handle two fields in less than one timeslice, and
you are careful to only ever process two fields when you have just
returned from a call to Thread.Sleep(1), then you should be guaranteed to
always be able to process those two fields before your timeslice is up.

In other words, you should be able to guarantee that you can always keep
two fields together.

It gets trickier if you want to try to send out more than one pair of
fields in a given timeslice, and of course you always run the risk of
having to wait some arbitrarily long amount of time once you've yielded
(or been preempted). But assuming you've got the system configured
properly, without extraneous software that might be burdening the CPU,
this shouldn't be an issue.
[...]
I have now come to the conclusion that there is something wrong with my
current installation. I have not tried moving it to other machines yet
since that is not quite so simple, but i will.
It's certainly worth a try. In any case, whatever computer you run this
one, you should go to great pains to disable _everything_ that is not
absolutely necessary. For sure, that rules out having any non-essential
third-party software. You will probably also want to research which
services can be safely disabled. A number of the services running by
default are not actually needed; you can use Google to find a number of
online articles regarding which ones can be turned off without disabling
your computer completely.

Pete

Jan 11 '08 #8

P: n/a
In other words, you should be able to guarantee that you can always keep
two fields together.
That is true. That much is certain. What is not a given is that the numbr of
frames where I prsent nothing new to the external hardware is an even
number.
If I send out paits of fields, which is good, but i send two, sleep while
the receiver expects another three fields, and then sends two more, then the
receiver will read my even fields as odd and vice versa.

It's certainly worth a try. In any case, whatever computer you run this
one, you should go to great pains to disable _everything_ that is not
absolutely necessary. For sure, that rules out having any non-essential
third-party software. You will probably also want to research which
services can be safely disabled. A number of the services running by
default are not actually needed; you can use Google to find a number of
online articles regarding which ones can be turned off without disabling
your computer completely.
Yes I should do that. It will be a pain though since it will eventually be
installed on a lot of machines.
Thanks for your feedback :-)

Jan 11 '08 #9

This discussion thread is closed

Replies have been disabled for this discussion.