Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Is anyone using Atomic Counters in their SMP programs?

Author: Robert Hyatt

Date: 21:57:44 04/28/00

Go up one level in this thread


On April 29, 2000 at 00:48:24, KarinsDad wrote:

>On April 28, 2000 at 20:45:37, Robert Hyatt wrote:
>
>>On April 28, 2000 at 13:28:22, KarinsDad wrote:
>>
>>>I read an interesting article by John M. Dlugosz titled "An Atomic Counter for
>>>Guaranteed Thread Safety" and was wondering if anyone was using this technique
>>>in their x86 SMP chess program. The article can be found in MSDN under
>>>Periodicals 1998/Visual C++ Developer/August.
>>>
>>>Since these techniques only appear to work for certain data types, I would
>>>assume that other techniques must also be used. What other techniques are being
>>>used?
>>>
>>>Also, this article implies that this works with multiple processors, but did not
>>>come right out and say it.
>>>
>>>This article also allows you to download source examples. And, some information
>>>can be found at:
>>>
>>>http://www.dlugosz.com/Repertoire/
>>>
>>>KarinsDad :)
>>
>>
>>I use pure spinlocks everywhere.  Simple and easy.  And very high performance.
>
>I'm not familiar with that term (and am too lazy at the moment to look it up).
>What is it and where would I find it in the Crafty source?
>
>KarinsDad :)


The Macros for Lock() and Unlock() are in lock.h.  They look like this:

#define Lock(volatile int lockvar) while (Exchange(lockvar,1)) while (lockvar)


#define UnLock(volatile int lockvar) Exchange(lockvar,0)



Lock works like this:  (assume lockvar is initialized to 0).  The Exchange()
macro is actually inline assembly to use the intel exchange(a,b) instruction,
which is an atomic instruction.  IE it reads the old value for A, and then
sets A=B, all in one bus transaction, guaranteeing that if multiple cpus do
this at the same time, one will get a value of zero, the rest will get a value
of one.

If the lock is set, rather than looping on the exchange(), which would lock
the bus frequently and smother other processors trying to get to memory, I then
do a normal spin loop in the second while.  So long as the lockvar is 1, it
will continue to spin.  However, lockvar gets loaded into L2 and then L1 cache
so that the spin uses no memory cycles at all.  When another cpu zeros lockvar,
the buss snooping cache controller will notice that a memory location has been
modified, while it has a local copy in its cache.  It marks it invalid, which
causes a new memory read to get the new value of zero.  To prevent race
conditions, I then drop out of that while, and go back to the original which
again does an Exchange(), hoping that this time it gets a zero, while
simultaneously setting the lock to 1.

Very simple, very efficient, and easy to use.  Before modifying any shared
data structure, its lock variable is acquired with the above.  A process can't
acquire the lock if another has already done so.  This implements critical
sections quite nicely.

If you want more details, feel free to ask...



This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.