0

Is it possible in C/C++, to "abandon" thread's CPU time? For example:

void wait(int s) //Low cpu usage
{
 int tmp = time();
 while(tmp + CLOCKS_PER_SEC * s > time())
  __AbandonCPUTime();
  //Tell cpu to do sth else.
}

I've tried Sleep(0), but it doesn't work.

tmp64128
  • 37
  • 1
  • 2
  • 1
    What are you trying to achieve? Sleep for a specific time without a busy loop? – Mario Feb 02 '13 at 18:39
  • 2
    Sleep(0) works, *but* to do much, there has to be some other thread ready to run. If the thread that just called Sleep is the only one that's read to run, it'll be scheduled/run again essentially immediately. – Jerry Coffin Feb 02 '13 at 18:40
  • That is probably an OS-dependent behavior. In Win32, you can use an event object for a thread to wait on, but that requires another thread to signal the event. Not sure if that helps. See http://stackoverflow.com/questions/4170272/does-waitforsingleobject-give-up-a-threads-time-slice – OldProgrammer Feb 02 '13 at 18:42
  • 1
    What's wrong with Sleep(s)? – Hans Passant Feb 02 '13 at 18:42
  • Don't loop. Sleep for the desired duration. Or perform a timedwait. – R.. GitHub STOP HELPING ICE Feb 02 '13 at 19:10
  • Hans Passant: Sleep(ms) also causes high cpu usage. – tmp64128 Feb 02 '13 at 19:16

4 Answers4

6

Look at C++11's:

#include <thread>
std::this_thread::yield();

Your CPU may support the _mm_pause() intrinsic (__asm__("pause") for gcc) which may or may not help you.

Otherwise you'll be looking at OS specific functions: sched_yield() for pthreads on Linux, or SwitchToThread() on Windows

James
  • 9,064
  • 3
  • 31
  • 49
  • None of these techniques will let the computer get into an idle state. _mm_pause() just tells the to spin more slowly. sched_yield() and SwitchToThread() (and Sleep(0)) don't specify how long the thread should yield and it is quite likely (especially on multi-core systems) that the thread will be immediately scheduled. The best answer is that you should wait for something -- operating systems have a rich set of primitives that let you wait for things to happen. Failing that, call Sleep() (or the equivalent posix function) with a non-zero delay so that you don't spin and waste power. – Bruce Dawson Nov 11 '14 at 00:58
  • re: `pause`: [Minimum time a thread can pause in Linux](https://stackoverflow.com/q/7371869) – Peter Cordes Aug 18 '18 at 12:02
4

Edit to answer the question more directly: you should either wait for something (WaitForSingleObject or GetMessage or some equivalent) or, if there isn't an event that you can wait for Sleep for some non-zero number of milliseconds.

Sleep(0) will typically return immediately so you still burn lots of energy and drain the user's battery or raise their power bill. Sleep(1) is still a hack but it is many orders of magnitude better than Sleep(0), _mm_pause(), sched_yield(), or SwitchToThread().

Sleep(0) on Windows will yield to another thread of the same priority if there is one that is waiting to run. This is rarely useful because, especially with dynamic adjustment of thread priorities, you can never tell whether there is another thread of the same priority. Sleep(0) generally won't switch to a thread of higher priority because that thread (being higher priority) would already be running. And it won't switch to a thread of lower priority, because it won't. SwitchToThread has similar problems.

_mm_pause() tells the CPU to go idle for a few cycles. This reduces power consumption and on a hyperthreaded machine lets the other thread on that core run faster. However this isn't something you should normally be doing.

If you want to wake up in n milliseconds then call Sleep(n). Or, better yet, wait on a specific event.

Functions like sched_yield, Sleep(0), and SwitchToThread are all generally bad ideas because they don't tell the OS when you want to run again.

Whatever you do don't busy wait, even with _mm_pause. http://randomascii.wordpress.com/2012/06/05/in-praise-of-idleness/

Bruce Dawson
  • 3,284
  • 29
  • 38
  • C++11 has [`std::this_thread::sleep_for`](https://en.cppreference.com/w/cpp/thread/sleep_for) for portable accurate sleeps. (see also [Can you implement a timer without a "sleep" in it using standard c++/c++11 only?](https://stackoverflow.com/a/51822039) TL:DR if you want to sleep, use a function called sleep. But as you say, it's not that `sleep()` is a bad way to sleep, it's that waiting for an event instead of sleeping for short intervals is much better). BTW, `_mm_pause()` on Skylake is about 100 cycles, up from about 5 on Sandybridge-family before that. – Peter Cordes Aug 18 '18 at 12:06
1

FYI, Intel have released two best practices on how to do what you want and it's mostly done via the use of _mm_pause(). Note that their gen 6 wait cycle times have been increased deliberately, so what you need is a combination of what's described in the following articles:

https://software.intel.com/en-us/articles/a-common-construct-to-avoid-the-contention-of-threads-architecture-agnostic-spin-wait-loops

https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops

Til
  • 5,150
  • 13
  • 26
  • 34
GlassBeaver
  • 196
  • 4
  • 15
0

sched_yield() "causes the calling thread to relinquish the CPU."

http://www.kernel.org/doc/man-pages/online/pages/man2/sched_yield.2.html

grep
  • 726
  • 7
  • 13
  • 2
    Using sched_yield is a terrible way to write multi-threaded code. From the documenation for sched_yield "If the calling thread is the only thread in the highest priority list at that time, it will continue to run after a call to sched_yield()." This is a very common scenario. If you call sched_yield in a loop then you just have a more complicated spin loop and you are wasting CPU time and electricity. Don't. Wait on something. https://randomascii.wordpress.com/2012/06/05/in-praise-of-idleness/ – Bruce Dawson Mar 12 '15 at 16:26