Пример #1
0
        // cutoff_occurred() checks whether a beta cutoff has occurred in the
        // current active split point, or in some ancestor of the split point.
        public bool cutoff_occurred()
        {
            for (SplitPoint sp = activeSplitPoint; sp != null; sp = sp.parentSplitPoint)
                if (sp.cutoff)
                    return true;

            return false;
        }
Пример #2
0
        public Thread(): base(){            
            searching = exit = false;
            maxPly = splitPointsSize = 0;
            activeSplitPoint = null;
            activePosition = null;
            idx = Engine.Threads.Count;

            for (int i = 0; i < MAX_SPLITPOINTS_PER_THREAD; i++)
                splitPoints[i] = new SplitPoint();
        }
Пример #3
0
        // split() does the actual work of distributing the work at a node between
        // several available threads. If it does not succeed in splitting the node
        // (because no idle threads are available), the function immediately returns.
        // If splitting is possible, a SplitPoint object is initialized with all the
        // data that must be copied to the helper threads and then helper threads are
        // told that they have been assigned work. This will cause them to instantly
        // leave their idle loops and call search(). When all threads have returned from
        // search() then split() returns.
        public void split(Position pos, Stack[] ss, int ssPos, Value alpha, Value beta, ref Value bestValue,
                                   ref Move bestMove, Depth depth, int moveCount,
                                   MovePicker movePicker, int nodeType, bool cutNode, bool Fake)
        {
            Debug.Assert(pos.pos_is_ok());
            Debug.Assert(-ValueS.VALUE_INFINITE < bestValue && bestValue <= alpha && alpha < beta && beta <= ValueS.VALUE_INFINITE);
            Debug.Assert(depth >= Engine.Threads.minimumSplitDepth);
            Debug.Assert(searching);
            Debug.Assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD);

            // Pick the next available split point from the split point stack
            SplitPoint sp = splitPoints[splitPointsSize];

            sp.masterThread = this;
            sp.parentSplitPoint = activeSplitPoint;
            sp.slavesMask.SetAll(false); sp.slavesMask[idx] = true;
            sp.depth = depth;
            sp.bestValue = bestValue;
            sp.bestMove = bestMove;           
            sp.alpha = alpha;
            sp.beta = beta;
            sp.nodeType = nodeType;
            sp.cutNode = cutNode;
            sp.movePicker = movePicker;
            sp.moveCount = moveCount;
            sp.pos = pos;
            sp.nodes = 0;
            sp.cutoff = false;
            sp.ss = ss;
            sp.ssPos = ssPos;


            // Try to allocate available threads and ask them to start searching setting
            // 'searching' flag. This must be done under lock protection to avoid concurrent
            // allocation of the same slave by another master.
            Engine.Threads.mutex.Lock();
            sp.mutex.Lock();

            sp.allSlavesSearching = true; // Must be set under lock protection
            ++splitPointsSize;
            activeSplitPoint = sp;
            activePosition = null;


            if (!Fake)
                for (Thread slave; (slave = Engine.Threads.available_slave(this)) != null; )
                {
                    sp.slavesMask[slave.idx] = true;
                    slave.activeSplitPoint = sp;
                    slave.searching = true; // Slave leaves idle_loop()
                    slave.notify_one(); // Could be sleeping
                }

            // Everything is set up. The master thread enters the idle loop, from which
            // it will instantly launch a search, because its 'searching' flag is set.
            // The thread will return from the idle loop when all slaves have finished
            // their work at this split point.            
            sp.mutex.UnLock();
            Engine.Threads.mutex.UnLock();        
    
            idle_loop_base(); // Force a call to base class idle_loop()//TODO, si se llama a la base??

            // In the helpful master concept, a master can help only a sub-tree of its
            // split point and because everything is finished here, it's not possible
            // for the master to be booked.
            Debug.Assert(!searching);
            Debug.Assert(activePosition == null);

            // We have returned from the idle loop, which means that all threads are
            // finished. Note that setting 'searching' and decreasing splitPointsSize is
            // done under lock protection to avoid a race with Thread::available_to().
            Engine.Threads.mutex.Lock();
            sp.mutex.Lock();
            

            searching = true;
            --splitPointsSize;
            activeSplitPoint = sp.parentSplitPoint;
            activePosition = pos;
            pos.set_nodes_searched(pos.nodes_searched() + sp.nodes);
            bestMove = sp.bestMove;
            bestValue = sp.bestValue;

            sp.mutex.UnLock();
            Engine.Threads.mutex.UnLock();
        }