Googles appar
Huvudmeny

Post a Comment On: cbloom rants

"07-29-11 - Spinning"

9 Comments -

1 – 9 of 9
Blogger won3d said...

Off thread, I asked you about _mm_pause. This post brings up another related question (although only academic interest to me, since I'm not doing windev anymore).

SwitchToThread has a return value. Is there anything sane you could do with it? The spinlock I used to have used to do a Sleep(0) if SwitchToThread returned false, but I wasn't very rigorous in figuring out if it helped or not.

July 29, 2011 at 8:21 PM

Blogger cbloom said...

"SwitchToThread has a return value. Is there anything sane you could do with it?"

That's a good question; I think the answer is no. It's nice that they return that though.

A Sleep(0) is not going to do anything good there because SwitchToThread does strictly more yielding than Sleep(0) ; you could do a Sleep(1) though.

I guess if you're in a spin and you know you must have another thread running and you SwitchToThread and it returns false, you could assert there.
Or if you knew the other thread holding the lock could be in some kind of wait, you could then break it out.

Another issue is that when you SwitchToThread in something like a spin lock you really would prefer to switch to a thread that's in your process, but that's not guaranteed.

July 29, 2011 at 8:47 PM

Blogger won3d said...

Since it's been forever, I looked up what SwitchToThread was doing:

"The yield of execution is in effect for up to one thread-scheduling time slice on the processor of the calling thread. The operating system will not switch execution to another processor, even if that processor is idle or is running a thread of lower priority."

And Sleep:

"A value of zero causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread continues execution.

Windows XP/2000: A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution. This behavior changed starting with Windows Server 2003."

So maybe:

if (!SwitchToThread()) Sleep(0);

is reasonable. SwitchToThread apparently only affects the current processor, not the entire system, so spinning on SwitchToThread might not help very much, although Sleep(0) might cause a thread to migrate from one processor to another. And I don't know if processor means an actual core, or a hyperthread.

July 29, 2011 at 10:03 PM

Blogger cbloom said...

I don't think so, but it's very hard to tell from the docs. Multi-proc scheduling on Windows is a bit hard to follow and not well documented.

"The operating system will not switch execution to another processor, even if that processor is idle or is running a thread of lower priority"

This is very confusing. I guess what it's saying is that after another thread swaps in and takes your place, you will always go into WAITING state, you won't get immediately moved to another processor, even if that processor is idle.

However, that's pretty standard for the Windows scheduler. Presumably if that other processor goes into its "I'm idle, get a thread" it would in fact take your thread.

It's unclear to me from that whether SwitchToThread will grab a thread from another processor to swap in for you or not. (?)

"A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run."

Does this mean on any processor? Is that different from STT or not?

The biggest difference between them that I know of is that Sleep(0) will not yield to lower priority threads but STT will. On single proc that means STT always does more yielding that Sleep 0.

Anyway, I don't think it can hurt. It makes some sense to do it the opposite way though, something like

Sleep(0)
if I wasn't swapped out , STT

July 29, 2011 at 10:32 PM

Blogger won3d said...

http://www.bluebytesoftware.com/blog/2006/08/23/PriorityinducedStarvationWhySleep1IsBetterThanSleep0AndTheWindowsBalanceSetManager.aspx

This link has some interesting info (although, it describes the older behavior for Sleep(0), which apparently cause starvation). It seems to suggest that SwitchToThread is better. The most interesting part is the "balance set manager" that is responsible for the priority and quantum boost heuristics. It was the first time I heard this name.

July 31, 2011 at 12:43 PM

Blogger cbloom said...

The fact that Sleep(0) isn't a reliable yield should be well known by now; that doesn't mean you should never use it, or you should use Sleep(1) (you shouldn't). In fact even with STT you might not make progress, which is why people wind up using exponential backoffs that go Sleep(0), then STT, then Sleep(1), etc.

Obviously a good software engineer doesn't just randomly stick calls to STT or whatever in their spin loops, they make a function like MySpinYield() and call their function so that they can encapsulate the tricky platform-specific knowledge in one place. It just staggers me how rarely I see anyone do things like this.

But really you shouldn't EVER do a spin-wait on Windows. There's no reason for it. Any place you are tempted to use a spin-wait, use an "eventcount" instead and do a proper wait. (perhaps after a few spins, but only if you have very good reason to believe those spins actually help)

BTW I've written about the balanced set manager in detail here :

http://cbloomrants.blogspot.com/2010/09/09-12-10-defficiency-of-windows-multi.html


Also BTW don't think "all my threads are the same priority, Sleep(0) is fine for me" - no they aren't. You have no idea what priority your threads are in Windows, they are changing constantly!! Even in a case where you tried to make threads of equal priority, Sleep(0) might just spin until some dynamic priority boost wears off.

July 31, 2011 at 12:59 PM

Blogger won3d said...

http://cbloomrants.blogspot.com/2010/09/09-12-10-defficiency-of-windows-multi.html

Wow, my memory is much worse than it used to be.

July 31, 2011 at 1:16 PM

Blogger Unknown said...

On modern versions of Windows (2K3 and later), SwitchToThread and Sleep(0) have similar behavior and they will only look at the current runqueue.

I think your overall thinking is good, though. Sleeps and SwitchToThread have no place in well-written multi-threaded code. Events and waitqueues are better.

September 17, 2011 at 1:00 PM

Blogger cbloom said...

"On modern versions of Windows (2K3 and later), SwitchToThread and Sleep(0) have similar behavior and they will only look at the current runqueue. "

Are you claiming that the well-documented difference WRST thread priorities is not true?

September 17, 2011 at 5:45 PM

You can use some HTML tags, such as <b>, <i>, <a>

This blog does not allow anonymous comments.

Comment moderation has been enabled. All comments must be approved by the blog author.

You will be asked to sign in after submitting your comment.