• Advertisement
Sign in to follow this  

boost::this_thread::sleep() precision only reaches milli?!

This topic is 2649 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there to ensure that my threads do not poll I have a method for getting the resolution of time taken to perform one cycle if its less than the desired time between cycles (in this case once per millisecond) I take the time remaining from the time taken and get this.

boost::this_thread::sleep(boost::posix_time::microseconds(997));

So it took 3 microseconds to process the data to run the thread. I want the thread to be performed every millisecond. So to be efficient I wait for 997 microseconds then go around a while loop again for the thread.

I looked in the function and it states.

inline void sleep(TimeDuration const& rel_time)
{
interruptible_wait(detail::pin_to_zero((long)rel_time.total_milliseconds()));
}

Can I make that rel_time.total_microseconds() without damaging anything?

Why is the precision not documented in the boost library?

Share this post


Link to post
Share on other sites
Advertisement
Thread sleep is usually bounded by the OS scheduler quantum. This can vary between OSes, but I've heard ~10ms is a good estimate. It can be more or less, depending on how busy the system is. sleep() generally means "sleep for at least this long". It is not deterministic. If you want really short sleeps, you'll want to spin instead. Even that, at any time you can be kicked off the processor and made wait for a quantum or more(unless that process chooses to sleep).

You cannot get real-time guarantees from a general purpose OS.

Share this post


Link to post
Share on other sites
I dont mind a hickup in precision of 5-10ms on the occasion but only being able to tune down to a 1000th of a second is madness. How can I possibly manage things at a milli seconds precision without being able to pause based on micro second timing!

Here is an example of why its plain dangerous to not have microsecond control.

If it took me 997micro seconds to do something and I pause for a millisecond because I can't read microseconds (even tho I can I just can't use them) and I want a relative ms between ticks (so I add in a ms wait due to the resolution limitation boost is inducing) thats 1.997ms per cycle!

Therefore without microsecond control you leave a valley of despair where real time could run at 50.0000000000000001% of real time!

I tried to rewrite it to take in microseconds but its treating them as milliseconds! which is as you can imagine not good for my real time game :p


namespace this_thread
{
void BOOST_THREAD_DECL yield();

bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(unsigned long microseconds)
{
//What do I have to do here to get microseconds is the invalid handle value the scope of measurement in some way or another?
interruptible_wait(detail::win32::invalid_handle_value,microseconds);

}
inline void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}

template<typename TimeDuration>
inline void sleep(TimeDuration const& rel_time)
{
interruptible_wait(detail::pin_to_zero((long)rel_time.total_microseconds()));
//interruptible_wait(detail::pin_to_zero((long)rel_time.total_milliseconds()));
}
inline void sleep(system_time const& abs_time)
{
interruptible_wait(abs_time);
}
}



I am open to an alternative for thread timing and power saving/efficiency but I see this as an issue in the library not in pragmatism. Unless your polling in every single game that has ever been created this is the only logical alternative for thread management I could see, everyone should be doing this.

Share this post


Link to post
Share on other sites
You can get between 5ms and I believe to 2 microseconds precision from the function QueryPerformanceCounter.

So with the code below I can show you how I am trying to get things done in terms of thread precision when the loops going too fast. There are other counter measures in place that work for lag at a precision of 5ms.



while (boolStopSafeRequest == false)
{
//On new machines the speed of the machine is dynamic so we need to query the frequency once per cycle :(
QueryPerformanceFrequency((LARGE_INTEGER*)&int64ClockFrequency);

//Get the number of ticks since we began doing anything.
//This is updated based on hardware on really old hardware the resolution is 12ms on normal hardware that could run this game thats 50,000 times thats 0.00002 a second!
QueryPerformanceCounter((LARGE_INTEGER*)&int64StartTimeTicks);

//Do some logic

//If we have done the function in less than the time between cycles we put the thread to sleep to save power!
QueryPerformanceCounter((LARGE_INTEGER*)&int64EndTimeTicks);

//Calculate to the millisecond the high performance tick against the clock speed.
int64DeltaTimeMicroSec = (int64EndTimeTicks - int64StartTimeTicks) * 1000000 / int64ClockFrequency;

//If we registered more than a millisecond of delay we just run the next cycle to chase up to realtime.
if (int64DeltaTimeMicroSec < 1000)//Every milliseconds we want to cycle so if we did everything faster than
//within our measure of a ms we wait one ms to garuntee we dont go super fast.
{
if (int64DeltaTimeMicroSec == 0)
{
//So wait for the full time between ticks
boost::this_thread::sleep(boost::posix_time::microseconds(1000));
}
else
{
//Get the inverse of the time in microseconds that was spent against the time we are waiting for.
int64DeltaTimeMicroSec = 1000 - int64DeltaTimeMicroSec;

boost::this_thread::sleep(boost::posix_time::microseconds(int64DeltaTimeMicroSec));
}
}


Share this post


Link to post
Share on other sites
Im gunna have to rewrite alot of library to get it all working at microsecond level without risking damaging something like a try_lock in milliseconds else where!

It looks possible to fully rewrite...

Does no one have an explanation as to what everyone else is doing? is it common practice for games to poll?

[Edited by - EnlightenedOne on October 22, 2010 4:03:31 PM]

Share this post


Link to post
Share on other sites
I have been defeated by the complexity of the boost library. I added in a performance counter in thread_data.hpp at the neccessary resolution. I changed all the mechanisms from milli to micro in several of the files linked to the component but still all my waits in microseconds now get treated as milliseconds passed in, so in short I need to keep at it.

I cannot believe I am the first one who has had such significant issues with timing at this level I still don't understand why the API lacked the support in the first place.

I have been told by other coders you cannot use the generic wait functions in c++ to make a native c++ thread wait per microsecond. So there must be a fix everyone uses to bypass needing a resolution of microseconds in a millisecond timed thread!

If you just wait for a millisecond if you know none have passed and tack on a wait for a millisecond how do you avoid the time delay threat of half speed if you perform a task at 0.999.. of a millisecond? I have this bad feeling in my stomach everyone must poll their code.

Please get in touch if you have a solution that doesn't pole.

Share this post


Link to post
Share on other sites
Quote:
Original post by EnlightenedOne
Does no one have an explanation as to what everyone else is doing? is it common practice for games to poll?
If you tell the OS to put a thread to sleep, then you have no control over when it wakes up! The value you give it is only a hint on how long to knock the thread out for.
On Windows, it will sleep for no less than the amount of milliseconds specified, and if still asleep after 5 seconds it will get out the smelling salts and start shaking the thread violently.

Putting a thread to sleep is not something that a game often wants to do... If you don't want to knock a thread out cold for an unpredictable amount of time, then sleep is not what you're looking for.

What are you trying to achieve with this sleeping? Are you trying to optimize a busy-wait / spin-lock?

[edit]
Here's a Windows-specific function that I use to wait on arbitrary conditions. It issues yield/pause/nop instructions and tries to make use of hyper-threading spin times, before telling the OS to sleep the thread for the shortest amount of time possible.
	template<class F> void YieldThreadUntil( F& func, uint spin )
{
while( true )
{
for( uint i=0; i!=spin; ++i )
{
if( func() )
return;
YieldProcessor();
if( func() )
return;
SwitchToThread();
}
if( func() )
return;
Sleep(0);
}
}
[Edit #2]BTW, what kind of variable is boolStopSafeRequest? Is it a native bool or some kind of atomic/volatile variable?

[Edit #3]Also, the "boost way" of doing this would be to wait on a condition variable, and notify the sleeping thread once boolStopSafeRequest has been set to true, however, that still enjoys the lack of sub-millisecond accuracy.

Share this post


Link to post
Share on other sites
On systems that support yielding the processor how long does it yield for? Ultimately yielding is just another attempt at pausing for scales that can be resolved to an aproximate of the microsecond level on machines that can support it. Thats good as it prevents old machines behaving wierdly to time and lets them just poll. Yield has no detail of timing on MSDN.... can you clarify the details of its behaviour?

I am trying to optimise a thread by making it sleep for a matter of microseconds in between cycles of operation.

If you can control between 0.002ms and aprox 10ms of accuracy and you have 1000 of these things per second your accuracy is between 500,000 and 100 measurements per second. If you want to manage your thread properly at a measurement running 1000 times per second and your precision is only 100 times per second you cannot pause at a precision neccessary to identify and keep a consistent realtime task in operation. You could run at ten times the speed you want to run at because if every task you do takes 9.9milliseconds to perform you wont know it took any time at all!

So you cannot time threads at the millisecond level properly with waits making the entire of the operating system an energy inefficient nightmare as every thread has to poll when it does not spin lock.

The safe boolean value is handled my a mutex. I decided to leave out for simplicity.

//Check if we should continue another cycle.
mutStopnError.lock();
boolStopSafeRequest = boolStopRequest;
mutStopnError.unlock();

Another thread locks a mutex in every threaded class and checks an integer indicating their status as a constant value which returns success/failure/safeexit. Theres alot of other stuff going on but that all works. The value is not "volatile" because that only garuntees for certain scenarios and I like to control my synchronisation like my threads very much to the dot :p

Share this post


Link to post
Share on other sites
I'm curious as to what work the thread is doing...
Is it not possible to convert it so it will be tolerant of non-deterministic time-steps (or is it already and the result isn't good enough)?

Share this post


Link to post
Share on other sites
It already does this to account for lag and rapid cycling using a delta time to 5 milliseconds or greater resolution using timeGetTime().

The thread can be made to poll and manage time relative to the millisecond but from an efficiency stand point at university I was taught this was the thread control equivelent of the go_to command in VB. When you do not have to poll waiting for another device you should not poll.

I wrote a stopwatch to the microsecond on some hardware before, so I assumed if a processor was capable of resolving to two microseconds of precision it should be capable of sleeping the thread for that level of resolution with a marginal accuracy loss compared to doing it in milliseconds.

I want to use query high performance counters capacity to determine microseconds to make my threads not be so wasteful. Things like the thread for handling input for a DX input device will not expand greatly or need to run faster than a millisecond for each cycle. All my threads were employing this dysfunctional syntax until I ran the test below.

I just wanted to add in a limit to the cycles for efficiency and good practice. I thought I had done this until I found out that anything below a millisecond and boosts threads do not wait at all. I tested it worked by making a counter that should trigger an if statement every 10 seconds of operation in my logic thread (which should obviously be 10000) this was of course running at a rate of microseconds as it was polling due to the wait function failing to identify a measure of time in microseconds.

Obviously the quantity to increment by could be modified by the delta of time passing to make it scale to the millisecond but that wouldn't help me get my threads to sleep and prove they were sleeping for an appropriate amount of time. I even tried to rewrite the boost library to no avail. It might be inherent of the language or OS that I cannot wait below a millisecond as the default thread available in c++ can only wait to a millisecond according to my trusted sources.

Share this post


Link to post
Share on other sites
If I wait for a millisecond anyway in a task that I want to run at most every millisecond and it takes 1.9ms to run. Then I use the timegettime's delta I still have that .9ms delay that would let met run at just under half the intended speed. But if I can resolve to a microsecond in my code could I use the delta from the high performance query against time to adjust for the 0.9 delay I am afraid of experiencing at the moment?

I think that would completely bypass the issue, however it would mean every movement relative to time would need to be scaled by a 64bit pointer relating to the actual time passed in microseconds.

Perhaps if I get the 64 bit int pointer for delta and I convert it to a less precise value before using it against all my scales of movement in time. I do not know how often the return value wraps around for the microsecond clock which might be an issue with doing stuff this way round.

I think that would work.... maybe an unsigned int would saffice to replace the 64bit int representing the microsecond by default.

Share this post


Link to post
Share on other sites
Why are you worried about this?
What problem are you trying to solve?

As already pointed out an OS like Windows is not 'real time' in any sense of the word; there are no garrentees about timing. If you say 'sleep(10)' then the OS is quite within its rights not to wake your thread you for say 2 days.

Something like 'yield' just says "I'm done with my thread time, give it to someone else if they want it and get back to me later".

This isn't really a problem in games because games aren't "real time" despite what you might think. Systems have tolences built in and you can construct a game loop which averages say 50 updates a second and the end user wouldn't be able to tell.

The situations where you want threads to sleep would be long latency tasks, such as disk IO, and the OS has systems in place to let you sleep your thread until those tasks are done.

In short, no fudging of numbers is going to give you this 'real time' requirement you seem to have in your head which probably isn't needed anyway.

So, I say again;
Why are you worried about this?
What problem are you trying to solve?

Share this post


Link to post
Share on other sites
Worry: Its generally bad practice to poll an operation which can be completed in a faster amound of time according to my lecturers.

Problem: Inefficiency in the rates between cycles/Bad practice/Power waste. It is ironic for a game to state such things but the input threaded class will waste 99% of your machine potential if it only needs to react every millisecond to an operation because it is reacting around a million times a second instead of this. It must be a significant power draining issue.

Not being in concise real time is both inherent and ok but making sure threads dont waste a lot of power is generally a good idea. I think making these processes run between 1000 and 500 times per second is an acceptable tollerance range as speed will be extrapolated by the microsecond delta anyway.

The very heart of the issue is abiding good practice.

Share this post


Link to post
Share on other sites
Quote:
Original post by EnlightenedOne
Problem: Inefficiency in the rates between cycles/Bad practice/Power waste. It is ironic for a game to state such things but the input threaded class will waste 99% of your machine potential if it only needs to react every millisecond to an operation because it is reacting around a million times a second instead of this. It must be a significant power draining issue.
So use your OS's built-in support for this. Mac's NSRunLoop, the Windows message pump, and I assume an equivalent on unix, are all designed to block until events are ready to be delivered - and thus don't consume all the CPU while they wait.

generally one doesn't bother with this in games, because the rendering/physics/AI are already running the CPU flat-out, so a few extra cycles spinning on input are irrelevant.

Share this post


Link to post
Share on other sites
YieldProcessor compiles to a low level instruction, which is designed to be inserted into spin-loops.
It either does nothing (old CPUs), switches execution to another hardware thread (engages "HyperThreading"), or lets the CPU know that you'd like to waste a cycle in the most power efficient way possible. If you want to waste a small amount of time in the most reliable and controlled manner, this is what you want.

SwitchToThread is a higher level function that gives the thread's current "quantum"/"time slice" back to the OS. Sleep(0) does much the same thing.
Seeing Windows is not a realtime OS, and it's quantums are measured in milliseconds, then you've got to accept millisecond-sized delays when using this method... Take note: when windows performs a pre-emptive context switch, your threads are already experience these unpredictable-sized delays at random intervals! Also take note that the mutex of yours has the potential to cause a "SwitchToThread" to occur internally!

If you want to get worked up about non-realtime desktop operating systems being to sloppy with thread control, check out Atom: PC CPU Task Parallelism Limits...

Both of the above are good power-saving measures. A SwitchToThread/Sleep once per frame is enough to stop your game from claiming 100% CPU usage, and YieldProcessor will make any spin-loops that you do require more efficient.


In practice though, again, you should just use a boost condition variable, which will put your thread to sleep and wake it up for you.
It usually doesn't matter if it sleeps for a millisecond too long. Or in the cases where it does matter, then you'll be using low-level constructs like YieldProcessor, atomic variables, memory fences, manual bus locking and the dreaded volatile keyword... If you're already using a mutex (power efficient, but very slow), then a condition variable isn't going to hurt much more.

Share this post


Link to post
Share on other sites
I guess I am just going to have to coincide with polling on this one as swift coder said with bulk its not going to hurt more than any other game engine will.

Thank you all for your input, at least I tried to find a better technique. Now to rewrite my timing mechanism to use a high performance counter for getting delta time passed so I can measure timing nicely.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement