コード例 #1
0
ファイル: ob.cs プロジェクト: SethKitchen/ChessAI
 internal static void init()
 {
     for (int i = 0; i < Constants.BROKER_SLOTS; i++)
     {
         _pool[i] = new LoopStack[0];
     }
 }
コード例 #2
0
ファイル: ob.cs プロジェクト: SethKitchen/ChessAI
        internal static void Free(LoopStack obj)
        {
            obj.Recycle();
#if WINDOWS_RT
            _cnt[Environment.CurrentManagedThreadId & Constants.BROKER_SLOT_MASK]--;
#else
            _cnt[System.Threading.Thread.CurrentThread.ManagedThreadId & Constants.BROKER_SLOT_MASK]--;
#endif
        }
コード例 #3
0
ファイル: ob.cs プロジェクト: SethKitchen/ChessAI
        internal static LoopStack GetObject()
        {
#if WINDOWS_RT
            int slotID = Environment.CurrentManagedThreadId & Constants.BROKER_SLOT_MASK;
#else
            int slotID = System.Threading.Thread.CurrentThread.ManagedThreadId & Constants.BROKER_SLOT_MASK;
#endif
            if (_cnt[slotID] == _pool[slotID].Length)
            {
                int         poolLength = _pool[slotID].Length;
                LoopStack[] temp       = new LoopStack[poolLength + Constants.BrokerCapacity];
                Array.Copy(_pool[slotID], temp, poolLength);
                for (int i = 0; i < Constants.BrokerCapacity; i++)
                {
                    temp[poolLength + i] = new LoopStack();
                }
                _pool[slotID] = temp;
            }
            return(_pool[slotID][_cnt[slotID]++]);
        }
コード例 #4
0
        /// Thread::idle_loop() is where the thread is parked when it has no work to do.
        /// The parameter 'master_sp', if non-NULL, is a pointer to an active SplitPoint
        /// object for which the thread is the master.
        internal void idle_loop(SplitPoint sp_master, ManualResetEvent initEvent)
        {
            if (initEvent != null)
            {
                // Signal done
                initEvent.Set();
            }

            bool use_sleeping_threads = Threads.useSleepingThreads;

            // If this thread is the master of a split point and all slaves have
            // finished their work at this split point, return from the idle loop.
            while ((sp_master == null) || (sp_master.slavesMask != 0))
            {
                // If we are not searching, wait for a condition to be signaled
                // instead of wasting CPU time polling for work.
                while (do_sleep ||
                       do_exit ||
                       (!is_searching && use_sleeping_threads))
                {
                    if (do_exit)
                    {
                        Debug.Assert(sp_master == null);
                        return;
                    }

                    // Grab the lock to avoid races with Thread::wake_up()
                    ThreadHelper.lock_grab(sleepLock);

                    // If we are master and all slaves have finished don't go to sleep
                    if ((sp_master != null) && (sp_master.slavesMask == 0))
                    {
                        ThreadHelper.lock_release(sleepLock);
                        break;
                    }

                    // Do sleep after retesting sleep conditions under lock protection, in
                    // particular we need to avoid a deadlock in case a master thread has,
                    // in the meanwhile, allocated us and sent the wake_up() call before we
                    // had the chance to grab the lock.
                    if (do_sleep || !is_searching)
                    {
                        ThreadHelper.cond_wait(sleepCond, sleepLock);
                    }

                    ThreadHelper.lock_release(sleepLock);
                }

                // If this thread has been assigned work, launch a search
                if (is_searching)
                {
                    Debug.Assert(!do_sleep && !do_exit);

                    ThreadHelper.lock_grab(Threads.splitLock);

                    Debug.Assert(is_searching);
                    SplitPoint sp = curSplitPoint;

                    ThreadHelper.lock_release(Threads.splitLock);

                    LoopStack ls    = LoopStackBroker.GetObject();
                    Stack[]   ss    = ls.ss;
                    int       ssPos = 0;

                    Position pos = PositionBroker.GetObject();
                    pos.copy(sp.pos, this);

                    Array.Copy(sp.ss, sp.ssPos - 1, ss, ssPos, 4);
                    ss[ssPos + 1].sp = sp;

                    ThreadHelper.lock_grab(sp.Lock);

                    if (sp.nodeType == NodeTypeC.Root)
                    {
                        Search.search(NodeTypeC.SplitPointRoot, pos, ss, ssPos + 1, sp.alpha, sp.beta, sp.depth);
                    }
                    else if (sp.nodeType == NodeTypeC.PV)
                    {
                        Search.search(NodeTypeC.SplitPointPV, pos, ss, ssPos + 1, sp.alpha, sp.beta, sp.depth);
                    }
                    else if (sp.nodeType == NodeTypeC.NonPV)
                    {
                        Search.search(NodeTypeC.SplitPointNonPV, pos, ss, ssPos + 1, sp.alpha, sp.beta, sp.depth);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    Debug.Assert(is_searching);

                    is_searching = false;
#if ACTIVE_REPARENT
                    sp.allSlavesRunning = false;
#endif
                    sp.slavesMask &= ~(1UL << idx);
                    sp.nodes      += pos.nodes;

                    // Wake up master thread so to allow it to return from the idle loop in
                    // case we are the last slave of the split point.
                    if (use_sleeping_threads &&
                        this != sp.master &&
                        !sp.master.is_searching)
                    {
                        sp.master.wake_up();
                    }

                    // After releasing the lock we cannot access anymore any SplitPoint
                    // related data in a safe way becuase it could have been released under
                    // our feet by the sp master. Also accessing other Thread objects is
                    // unsafe because if we are exiting there is a chance are already freed.
                    ThreadHelper.lock_release(sp.Lock);

#if ACTIVE_REPARENT
                    // Try to reparent to the first split point, with still all slaves
                    // running, where we are available as a possible slave.
                    for (int i = 0; i < Threads.size(); i++)
                    {
                        Thread     th     = Threads.threads[i];
                        int        spCnt  = th.splitPointsCnt;
                        SplitPoint latest = th.splitPoints[spCnt != 0 ? spCnt - 1 : 0];

                        if (this.is_available_to(th) &&
                            spCnt > 0 &&
                            !th.cutoff_occurred() &&
                            latest.allSlavesRunning &&
                            Utils.more_than_one(latest.slavesMask))
                        {
                            ThreadHelper.lock_grab(latest.Lock);
                            ThreadHelper.lock_grab(Threads.splitLock);

                            // Retest all under lock protection, we are in the middle
                            // of a race storm here !
                            if (this.is_available_to(th) &&
                                spCnt == th.splitPointsCnt &&
                                !th.cutoff_occurred() &&
                                latest.allSlavesRunning &&
                                Utils.more_than_one(latest.slavesMask))
                            {
                                latest.slavesMask |= 1UL << idx;
                                curSplitPoint      = latest;
                                is_searching       = true;
                            }

                            ThreadHelper.lock_release(Threads.splitLock);
                            ThreadHelper.lock_release(latest.Lock);

                            break; // Exit anyhow, only one try (enough in 99% of cases)
                        }
                    }
#endif

                    pos.startState = null;
                    pos.st         = null;
                    PositionBroker.Free();
                    LoopStackBroker.Free(ls);
                }
            }
        }
コード例 #5
0
ファイル: ob.cs プロジェクト: SethKitchen/ChessAI
        internal static void Warmup()
        {
            // Bench 128 4 17 yields:

            // CheckInfoBroker: 140 (4/32/40/32/32)
            // EvalInfoBroker: 16 (4/4/4/4)
            // SwapListBroker: 16 (4/4/4/4)
            // MovesSearchedBroker: 120 (28/36/28/28)
            // PositionBroker: 32 (8/8/8/8)
            // StateInfoArrayBroker: 16 (4/4/4/4)

            // MListBroker: 20 (4/4/4/4/4)
            // LoopStackBroker: 32 (8/8/8/8)
            // MovePickerBroker: 136 (32/40/32/32)
            // StateInfoBroker: 132 (32/36/32/32)

            // Specific allocation not to overallocate memory for nothing
            int i, brokerSize;

            // Reusing brokers
            brokerSize = 40; for (i = 0; i < brokerSize; i++)
            {
                CheckInfoBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                CheckInfoBroker.Free();
            }
            brokerSize = 4; for (i = 0; i < brokerSize; i++)
            {
                EvalInfoBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                EvalInfoBroker.Free();
            }
            brokerSize = 4; for (i = 0; i < brokerSize; i++)
            {
                SwapListBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                SwapListBroker.Free();
            }
            brokerSize = 36; for (i = 0; i < brokerSize; i++)
            {
                MovesSearchedBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                MovesSearchedBroker.Free();
            }
            brokerSize = 8; for (i = 0; i < brokerSize; i++)
            {
                PositionBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                PositionBroker.Free();
            }
            brokerSize = 4; for (i = 0; i < brokerSize; i++)
            {
                StateInfoArrayBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                StateInfoArrayBroker.Free();
            }
            brokerSize = 4; for (i = 0; i < brokerSize; i++)
            {
                MListBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                MListBroker.Free();
            }
            brokerSize = 36; for (i = 0; i < brokerSize; i++)
            {
                StateInfoBroker.GetObject();
            }
            for (i = 0; i < brokerSize; i++)
            {
                StateInfoBroker.Free();
            }

            // Recycling brokers
            brokerSize = 8; LoopStack[] arrLoopStack = new LoopStack[brokerSize]; for (i = 0; i < brokerSize; i++)
            {
                arrLoopStack[i] = LoopStackBroker.GetObject();
            }
            for (i = brokerSize - 1; i >= 0; i--)
            {
                LoopStackBroker.Free(arrLoopStack[i]);
            }
            brokerSize = 40; MovePicker[] arrMovePicker = new MovePicker[brokerSize]; for (i = 0; i < brokerSize; i++)
            {
                arrMovePicker[i] = MovePickerBroker.GetObject();
            }
            for (i = brokerSize - 1; i >= 0; i--)
            {
                MovePickerBroker.Free(arrMovePicker[i]);
            }
        }