Only Evaluates as True when Thread Sleeps - c++

I am getting some unexpected behavior I don't understand. I am trying to implement a fixed variable time step as described from http://gafferongames.com/game-physics/fix-your-timestep/ and http://gameprogrammingpatterns.com/game-loop.html. My inner while loop never evaluates as true when I run the program in visual studio; however, when I uncomment 'this_thread::sleep_for(1s)', the while loop will evaluate as a true after the outer loop executes 10 times or so. I would expect on faster machines, this would be the expected outcome.
So my question is why would the inner loop only evaluate as true when the 'this_thread::sleep_for(1s)' is uncommented? Shouldn't lagTime become greater than fixedDeltaTime regardless of the sleep_for? Does the math take too much time for the computer or something?
int updateCount = 0;
double CLOCKS_PER_MILLISECOND((double)CLOCKS_PER_SEC * 1000.0);
double previousTime = std::clock() / CLOCKS_PER_MILLISECOND;
double newTime = 0, deltaTime = 0, lagTime = 0;
double fixedDeltaTime = 1.0 / 60.0;
while (gameIsRunning)
{
newTime = std::clock() / CLOCKS_PER_MILLISECOND;
deltaTime = newTime - previousTime;
previousTime = newTime;
lagTime += deltaTime;
inputSystem.update();
sceneManager.update();
while(lagTime >= fixedDeltaTime) // never evalutes as true?
{
physicsSystem.update();
lagTime -= fixedDeltaTime;
updateCount++;
}
std::cerr << "-----" << updateCount << "-----" << std::endl;
physicsSystem.interpolate(lagTime / fixedDeltaTime);
renderSystem.update();
audioSystem.update();
updateCount = 0;
//std::this_thread::sleep_for(1s);
}
Thank you for any help!

You're trying to measure time using clock(), but that is a process tick counter that won't advance while all threads in your process are sleeping. The whole point of sleep is to tell the CPU "don't give this process any attention for a while!". As far as your program is concerned, time freezes while it's asleep.
If you waited long enough, lagTime would eventually advance past fixedDeltaTime because the period of time during which your program is not sleeping consumes ticks ... but you'd have to wait for many, many seconds.
Don't use clock() to measure the absolute passage of time.

Related

Why am I not getting a test_time close to 5 seconds?

I'am trying to make a time meter. My OS is Windows.Here is a small piece of code that gives a strange result. If a thread sleeps for 1ms and does this 5000 times, then I would expect it to take roughly 5 seconds. But I get as a result that test_time = 12.8095
Do not understand why?
How can I fix the code so that I get a time meter that can measure durations of about 1 millisecond?
std::atomic_bool work = true;
size_t cnt{};
std::chrono::duration<double> operation_time;
double test_time;
auto start_time_ = std::chrono::high_resolution_clock::now();
std::thread counter_ = std::thread([&work, &cnt]() {
while (work) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
cnt++;
if (cnt >= 5000)
work = false;
}
});
if (counter_.joinable())
counter_.join();
operation_time = std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - start_time_);
test_time = operation_time.count();
std::cout << "test_time = " << test_time << std::endl;
As previously stated, sleep_for
Blocks the execution of the current thread for at least the specified sleep_duration.
The answer to your question would be to use sleep_until
Blocks the execution of the current thread until specified sleep_time has been reached.
That means, take the current timestamp, add 1 ms and sleep until that time.
See:
https://en.cppreference.com/w/cpp/thread/sleep_for
https://en.cppreference.com/w/cpp/thread/sleep_until

std::this_thread::sleep_until timing is completely off by about a factor of 2, inexplicably

Ok, I really have no idea why this is happening. I'm currently implementing a thread container which runs an infinite loop in a detached manner, limited to a certain speed between each iteration.
Header:
class timeloop
{
public:
std::thread thread = { };
bool state = true;
void (*function_pointer)() = nullptr;
double ratio = 1.0f;
std::chrono::nanoseconds elapsed = { };
timeloop(
void (*function_pointer)() = nullptr
);
void function();
};
Definition:
void timeloop::start()
{
this->thread = std::thread(
&loop::function,
this
);
}
void timeloop::function()
{
std::chrono::steady_clock::time_point next;
std::chrono::steady_clock::time_point start;
std::chrono::steady_clock::time_point end;
while (
this->state
)
{
start = std::chrono::high_resolution_clock::now();
next = start + std::chrono::nanoseconds(
(long long) (this->ratio * (double) std::chrono::nanoseconds::period::den)
);
if (
this->function_pointer != nullptr
)
{
this->function_pointer();
}
/***************************
this is the culprit
***************************/
std::this_thread::sleep_until(
next
);
end = std::chrono::high_resolution_clock::now();
this->elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(
end - start
);
}
}
Calling code:
timeloop* thread_draw = new timeloop(
&some_void_function
);
thread_draw->ratio = 1.0 / 128.0;
thread_draw->start();
thread_draw->thread.detach();
The definition code is behaving weirdly, specifically std::this_thread::sleep_until. With this->ratio = 1.0 / 128.0 I'm expecting a framerate of around 128, the computed values of start and next reinforce this, yet it inexplicably hovers at around 60. And yeah, I tried just dividing next by 2, but that actually made it drop to around 40.
Extra code to verify the normal time to sleep for:
auto diff = std::chrono::nanoseconds(
next - start
).count() / (double) std::chrono::nanoseconds::period::den;
auto equal = diff == this->ratio;
where equal evaluates to true.
Frame rate calculation:
double time = (double) thread_draw->elapsed.count() / (double) std::chrono::nanoseconds::period::den;
double fps = 1.0 / time;
Though I also used external FPS counters to verify (NVIDIA ShadowPlay and RivaTuner/MSI Afterburner), and they were in a range of about +-5 of the calculated value.
And I know it's std::this_thread::sleep_until because once I comment that out, the frame rate jumps up to around 2000. Yeah...
I'm truly baffled at this, especially seeing how I can't find any evidence of anybody else ever having had this problem. And yes, I'm aware that sleep functions aren't perfectly accurate, and there's bound to be hiccups every now and then, but consistently sleeping for pretty much double the scheduled time is just absurd.
Did I perhaps misconfigure a compiler option or something? It's definitely not a performance problem, and I'm reasonably sure it's not a logic error either (seeing how all the calculations check out) [unless I'm abusing chrono somewhere].
There are no guarantees on resolution of sleep_until, you are only guaranteed the thread will not be woken before the timepoint. If you are implementing the main game loop, read Fix your timestep.
Using sleep to guarantee timing is a terrible way to do it. You are at mercy of OS scheduler and e.g. Windows has a minimal sleep amount about 10 milliseconds I believe. (If the implementation actually asks the OS to put the thread to sleep and the OS decides to do a context switch.)
The lag might also be caused by VSync in the drawing thread if you are calling glfwSwapBuffers or similar. That would explain why your are limited to 60FPS, but not why commenting sleep solves the problem.
So my guess is the OS's sleep above. I would recommend to remove the sleep and rely on VSync, that's the right frequency you want to draw at anyway. Synchronization with logic threads will be a pain in... but that's always the case.
I think your problem is you are not using absolute timing because you keep resetting your absolute time point next relative to the current time now().
Try changing this:
while (
this->state
)
{
start = std::chrono::high_resolution_clock::now();
next = start + std::chrono::nanoseconds(
(long long) (this->ratio * (double) std::chrono::nanoseconds::period::den)
);
// ...
to this
// before the loop
next = std::chrono::high_resolution_clock::now();
while (
this->state
)
{
// keep the timing absolute by adding to the absolute time point
next = next + std::chrono::nanoseconds(
(long long) (this->ratio * (double) std::chrono::nanoseconds::period::den)
);
// ...
That way you call now() only once and then all your subsequent timings are absolutely (as opposed to relatively) calculated from that point.
Edited to add:
Additionally, I would avoid using std::chrono::high_resolution_clock. It is often just an alias of std::chrono::system_clock which is subject to random time alterations as the system clock attempts to remain synchronized with internet time.
Use std::chrono::steady_clock.

problem with resetting window repeat clock at c++

problem with resetting window while repeat clock at c++
I tried to reset the time using time, chrono. However, the code execution time continued to increase without initialization.
Hello, I'm a student at the Korea Institute of Technology. Use the translator.
Please excuse me for speaking awkwardly.
I'm designing a program that uses the C++ OpenPose library to measure the right PC user tax.
Basically, we've completed the function of floating a pop-up to provide feedback when your right shoulder or left shoulder is crooked.
However, I would like to issue an alert after a certain second rather than a feedback that is sent in the wrong position.
Time should be measured when the supose function is not executed, but when the user is sitting in the wrong position. Time will be measured from the time when the supose function is executed. An event should occur if the same seat is held for 20 seconds from the wrong seat.
The event will occur after 20 seconds, and if the time is not initialized, it will occur as soon as it is recognized as an incorrect posture. I think it's because of when. If the library breaks from where, it ends with 0 code.
Once I've solved the time-related function, I'm going to ask you a question because I'm having a hard time completing the program.
Thank you.
while (!userWantsToExit)
{
// start frame
std::shared_ptr<std::vector<UserDatum>> datumProcessed;
if (opWrapper.waitAndPop(datumProcessed))
{
userWantsToExit = userOutputClass.display(datumProcessed);
userOutputClass.printKeypoints(datumProcessed);
....
//string to int
int subShoulder = stoi(rShoulderY) - stoi(lShoulderY);
//clac keypoint values for posedata
if (50 < subShoulder || -50 > subShoulder)
{
if (stoi(rShoulderY) < stoi(lShoulderY)) {
clock_t t_start, t_end;
int time;
t_start = clock(); //start clock
time = t_start / CLOCKS_PER_SEC;
op::log(time);
if (time > 20) {
t_end = clock(); //end clock
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
cv::imshow("SUPOSE", imgLshoulderDown);
std::string id = "hjw";
std::string pose = "leftShoulder";
httpRequestPose(id, pose);
}
}
else if (stoi(rShoulderY) > stoi(lShoulderY)) {
clock_t t_start, t_end;
int time;
t_start = clock(); //start clock
time = t_start / CLOCKS_PER_SEC;
op::log(time);
if (time > 20) {
cv::imshow("SUPOSE", imgRshoulderDown);
std::string id = "hjw";
std::string pose = "rightShoulder";
httpRequestPose(id, pose);
}
t_end = clock();
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
}
else {
clock_t t_start, t_end;
int time;
t_end = clock();
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
}
}
}
else {}
//op::log("Processed datum could not be emplaced.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
}
*image
Honestly, it is very hard for me to completely understand your question. However, I was a student and not good at english (even now), i know how struggling it was to find help with google translated paragraphs. Hence, i will make a try.
As I understand, you want to trigger an alert if the shoulder keeps inclining left for more than 20 seconds (same to right incline). Is that correct?
If it is correct, I think the problem is that you keep the variable t_start inside the poseDetect function. It means that everytime the pose is detected the t_start is a new one. The value (t_end - t_start) is always 0. You should declare t_start outside of that function and use a flag to check if it is the first time. I would like to suggest with below pseudo code
bool isLeftIncline = false;
clock_t startLeft=clock(); //get current time
void poseDetect()
{
if (50 < subShoulder || -50 > subShoulder){
if (stoi(rShoulderY) < stoi(lShoulderY)){ // should is inclined to the left
if(!isLeftIncline){ // the first time
startLeft=clock(); // get the starting time
isLeftIncline=true;
//trigger for the first time here
}else { // after the first time
clock_t current=clock();
int timeDiff=current-startLeft;
if(timeDiff>20){ //after 20 second with same pose
// issue an alert
}
//or trigger alert every nearly 20 seconds
//if(timeDiff%20<3){
//trigger
//}
}
}else {
// the shoulder no longer inclines to the left
// reset isLeftIncline time
isLeftIncline = false;
}
// you can apply the same for the right incline here
}
}

Odd results when adding artificial delays to C++ code. Embedded Linux

I have been looking at the performance of our C++ server application running on embedded Linux (ARM). The pseudo code for the main processing loop of the server is this -
for i = 1 to 1000
Process item i
Sleep for 20 ms
The processing for one item takes about 2ms. The "Sleep" here is really a call to the Poco library to do a "tryWait" on an event. If the event is fired (which it never is in my tests) or the time expires, it comes returns. I don't know what system call this equates to. Although we ask for a 2ms block, it turns out to be roughly 20ms. I can live with that - that's not the problem. The sleep is just an artificial delay so that other threads in the process are not starved.
The loop takes about 24 seconds to go through 1000 items.
The problem is, we changed the way the sleep is used so that we had a bit more control. I mean - 20ms delay for 2ms processing doesn't allow us to do much processing. With this new parameter set to a certain value it does something like this -
For i = 1 to 1000
Process item i
if i % 50 == 0 then sleep for 1000ms
That's the rough code, in reality the number of sleeps is slightly different and it happens to work out at a 24s cycle to get through all the items - just as before.
So we are doing exactly the same amount of processing in the same amount of time.
Problem 1 - the CPU usage for the original code is reported at around 1% (it varies a little but that's about average) and the CPU usage reported for the new code is about 5%. I think they should be the same.
Well perhaps this CPU reporting isn't accurate so I thought I'd sort a large text file at the same time and see how much it's slowed up by our server. This is a CPU bound process (98% CPU usage according to top). The results are very odd. With the old code, the time taken to sort the file goes up by 21% when our server is running.
Problem 2 - If the server is only using 1% of the CPU then wouldn't the time taken to do the sort be pretty much the same?
Also, the time taken to go through all the items doesn't change - it's still 24 seconds with or without the sort running.
Then I tried the new code, it only slows the sort down by about 12% but it now takes about 40% longer to get through all the items it has to process.
Problem 3 - Why do the two ways of introducing an artificial delay cause such different results. It seems that the server which sleeps more frequently but for a minimum time is getting more priority.
I have a half baked theory on the last one - whatever the system call that is used to do the "sleep" is switching back to the server process when the time is elapsed. This gives the process another bite at the time slice on a regular basis.
Any help appreciated. I suspect I'm just not understanding it correctly and that things are more complicated than I thought. I can provide more details if required.
Thanks.
Update: replaced tryWait(2) with usleep(2000) - no change. In fact, sched_yield() does the same.
Well I can at least answer problem 1 and problem 2 (as they are the same issue).
After trying out various options in the actual server code, we came to the conclusion that the CPU reporting from the OS is incorrect. It's quite result so to make sure, I wrote a stand alone program that doesn't use Poco or any of our code. Just plain Linux system calls and standard C++ features. It implements the pseudo code above. The processing is replaced with a tight loop just checking the elapsed time to see if 2ms is up. The sleeps are proper sleeps.
The small test program shows exactly the same problem. i.e. doing the same amount of processing but splitting up the way the sleep function is called, produces very different results for CPU usage. In the case of the test program, the reported CPU usage was 0.0078 seconds using 1000 20ms sleeps but 1.96875 when a less frequent 1000ms sleep was used. The amount of processing done is the same.
Running the test on a Linux PC did not show the problem. Both ways of sleeping produced exactly the same CPU usage.
So clearly a problem with our embedded system and the way it measures CPU time when a process is yielding so often (you get the same problem with sched_yeild instead of a sleep).
Update: Here's the code. RunLoop is where the main bit is done -
int sleepCount;
double getCPUTime( )
{
clockid_t id = CLOCK_PROCESS_CPUTIME_ID;
struct timespec ts;
if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
return (double)ts.tv_sec +
(double)ts.tv_nsec / 1000000000.0;
return -1;
}
double GetElapsedMilliseconds(const timeval& startTime)
{
timeval endTime;
gettimeofday(&endTime, NULL);
double elapsedTime = (endTime.tv_sec - startTime.tv_sec) * 1000.0; // sec to ms
elapsedTime += (endTime.tv_usec - startTime.tv_usec) / 1000.0; // us to ms
return elapsedTime;
}
void SleepMilliseconds(int milliseconds)
{
timeval startTime;
gettimeofday(&startTime, NULL);
usleep(milliseconds * 1000);
double elapsedMilliseconds = GetElapsedMilliseconds(startTime);
if (elapsedMilliseconds > milliseconds + 0.3)
std::cout << "Sleep took longer than it should " << elapsedMilliseconds;
sleepCount++;
}
void DoSomeProcessingForAnItem()
{
timeval startTime;
gettimeofday(&startTime, NULL);
double processingTimeMilliseconds = 2.0;
double elapsedMilliseconds;
do
{
elapsedMilliseconds = GetElapsedMilliseconds(startTime);
} while (elapsedMilliseconds <= processingTimeMilliseconds);
if (elapsedMilliseconds > processingTimeMilliseconds + 0.1)
std::cout << "Processing took longer than it should " << elapsedMilliseconds;
}
void RunLoop(bool longSleep)
{
int numberOfItems = 1000;
timeval startTime;
gettimeofday(&startTime, NULL);
timeval startMainLoopTime;
gettimeofday(&startMainLoopTime, NULL);
for (int i = 0; i < numberOfItems; i++)
{
DoSomeProcessingForAnItem();
double elapsedMilliseconds = GetElapsedMilliseconds(startTime);
if (elapsedMilliseconds > 100)
{
std::cout << "Item count = " << i << "\n";
if (longSleep)
{
SleepMilliseconds(1000);
}
gettimeofday(&startTime, NULL);
}
if (longSleep == false)
{
// Does 1000 * 20 ms sleeps.
SleepMilliseconds(20);
}
}
double elapsedMilliseconds = GetElapsedMilliseconds(startMainLoopTime);
std::cout << "Main loop took " << elapsedMilliseconds / 1000 <<" seconds\n";
}
void DoTest(bool longSleep)
{
timeval startTime;
gettimeofday(&startTime, NULL);
double startCPUtime = getCPUTime();
sleepCount = 0;
int runLoopCount = 1;
for (int i = 0; i < runLoopCount; i++)
{
RunLoop(longSleep);
std::cout << "**** Done one loop of processing ****\n";
}
double endCPUtime = getCPUTime();
std::cout << "Elapsed time is " <<GetElapsedMilliseconds(startTime) / 1000 << " seconds\n";
std::cout << "CPU time used is " << endCPUtime - startCPUtime << " seconds\n";
std::cout << "Sleep count " << sleepCount << "\n";
}
void testLong()
{
std::cout << "Running testLong\n";
DoTest(true);
}
void testShort()
{
std::cout << "Running testShort\n";
DoTest(false);
}

precise time measurement

I'm using time.h in C++ to measure the timing of a function.
clock_t t = clock();
someFunction();
printf("\nTime taken: %.4fs\n", (float)(clock() - t)/CLOCKS_PER_SEC);
however, I'm always getting the time taken as 0.0000. clock() and t when printed separately, have the same value. I would like to know if there is way to measure the time precisely (maybe in the order of nanoseconds) in C++ . I'm using VS2010.
C++11 introduced the chrono API, you can use to get nanoseconds :
auto begin = std::chrono::high_resolution_clock::now();
// code to benchmark
auto end = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count() << "ns" << std::endl;
For a more relevant value it is good to run the function several times and compute the average :
auto begin = std::chrono::high_resolution_clock::now();
uint32_t iterations = 10000;
for(uint32_t i = 0; i < iterations; ++i)
{
// code to benchmark
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count();
std::cout << duration << "ns total, average : " << duration / iterations << "ns." << std::endl;
But remember the for loop and assigning begin and end var use some CPU time too.
I usually use the QueryPerformanceCounter function.
example:
LARGE_INTEGER frequency; // ticks per second
LARGE_INTEGER t1, t2; // ticks
double elapsedTime;
// get ticks per second
QueryPerformanceFrequency(&frequency);
// start timer
QueryPerformanceCounter(&t1);
// do something
...
// stop timer
QueryPerformanceCounter(&t2);
// compute and print the elapsed time in millisec
elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
The following text, that i completely agree with, is quoted from Optimizing software in C++ (good reading for any C++ programmer) -
The time measurements may require a very high resolution if time
intervals are short. In Windows, you can use the
GetTickCount or
QueryPerformanceCounter functions for millisecond resolution. A much
higher resolution can be obtained with the time stamp counter in the
CPU, which counts at the CPU clock frequency.
There is a problem that "the clock frequency may vary dynamically and that
measurements are unstable due to interrupts and task switches."
In C or C++ I usually do like below. If it still fails you may consider using rtdsc functions
struct timeval time;
gettimeofday(&time, NULL); // Start Time
long totalTime = (time.tv_sec * 1000) + (time.tv_usec / 1000);
//........ call your functions here
gettimeofday(&time, NULL); //END-TIME
totalTime = (((time.tv_sec * 1000) + (time.tv_usec / 1000)) - totalTime);