Skip to content

Commit 1498719

Browse files
implement UCI option to set search thread count
1 parent cb0a624 commit 1498719

File tree

5 files changed

+50
-30
lines changed

5 files changed

+50
-30
lines changed

balancer.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,11 @@ import (
3131
// with the SP before sending the SP to the worker to avoid a data race with the SP's
3232
// WaitGroup.
3333

34-
const (
35-
MAX_WORKERS = 8
36-
)
37-
3834
var loadBalancer *Balancer
3935

4036
func setupLoadBalancer(numCPU int) {
41-
numWorkers := uint8(min(numCPU, MAX_WORKERS))
42-
loadBalancer = NewLoadBalancer(numWorkers)
43-
loadBalancer.Start()
37+
loadBalancer = NewLoadBalancer(uint8(numCPU))
38+
loadBalancer.Start(numCPU)
4439
}
4540

4641
func NewLoadBalancer(numWorkers uint8) *Balancer {
@@ -64,14 +59,18 @@ func NewLoadBalancer(numWorkers uint8) *Balancer {
6459

6560
type Balancer struct {
6661
workers []*Worker
67-
sync.Mutex
62+
// sync.Mutex
63+
once sync.Once
6864
done chan *Worker
6965
}
7066

71-
func (b *Balancer) Start() {
72-
for _, w := range b.workers[1:] {
73-
w.Help(b) // Start each worker except for the root worker.
74-
}
67+
func (b *Balancer) Start(numCPU int) {
68+
b.once.Do(func() {
69+
// fmt.Printf("Initializing %d workers\n", numCPU)
70+
for _, w := range b.workers[1:] {
71+
w.Help(b) // Start each worker except for the root worker.
72+
}
73+
})
7574
}
7675

7776
func (b *Balancer) Overhead() int {

board.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,41 +187,41 @@ func (brd *Board) ValidMove(m Move, inCheck bool) bool {
187187
case KING:
188188
if abs(to-from) == 2 { // validate castle moves
189189
occ := brd.AllOccupied()
190-
if c == WHITE && (brd.castle&12) > 0 {
190+
if c == WHITE && !inCheck && (brd.castle&12) > 0 {
191191
switch to {
192192
case C1:
193-
if !inCheck && (brd.castle&C_WQ > uint8(0)) && castleQueensideIntervening[WHITE]&brd.AllOccupied() == 0 &&
194-
!isAttackedBy(brd, occ, B1, e, c) && !isAttackedBy(brd, occ, C1, e, c) && !isAttackedBy(brd, occ, D1, e, c) {
193+
if (brd.castle&C_WQ > uint8(0)) && castleQueensideIntervening[WHITE]&occ == 0 &&
194+
!isAttackedBy(brd, occ, B1, e, c) && !isAttackedBy(brd, occ, C1, e, c) &&
195+
!isAttackedBy(brd, occ, D1, e, c) {
195196
return true
196197
}
197198
case G1:
198-
if !inCheck && (brd.castle&C_WK > uint8(0)) && castleKingsideIntervening[WHITE]&brd.AllOccupied() == 0 &&
199+
if (brd.castle&C_WK > uint8(0)) && castleKingsideIntervening[WHITE]&occ == 0 &&
199200
!isAttackedBy(brd, occ, F1, e, c) && !isAttackedBy(brd, occ, G1, e, c) {
200201
return true
201202
}
202203
}
203-
} else if c == BLACK && (brd.castle&3) > 0 {
204+
} else if c == BLACK && !inCheck && (brd.castle&3) > 0 {
204205
switch to {
205206
case C8:
206-
if !inCheck && (brd.castle&C_BQ > uint8(0)) && castleQueensideIntervening[BLACK]&brd.AllOccupied() == 0 &&
207-
!isAttackedBy(brd, occ, B8, e, c) && !isAttackedBy(brd, occ, C8, e, c) && !isAttackedBy(brd, occ, D8, e, c) {
207+
if (brd.castle&C_BQ > uint8(0)) && castleQueensideIntervening[BLACK]&occ == 0 &&
208+
!isAttackedBy(brd, occ, B8, e, c) && !isAttackedBy(brd, occ, C8, e, c) &&
209+
!isAttackedBy(brd, occ, D8, e, c) {
208210
return true
209211
}
210212
case G8:
211-
if !inCheck && (brd.castle&C_BK > uint8(0)) && castleKingsideIntervening[BLACK]&brd.AllOccupied() == 0 &&
213+
if (brd.castle&C_BK > uint8(0)) && castleKingsideIntervening[BLACK]&occ == 0 &&
212214
!isAttackedBy(brd, occ, F8, e, c) && !isAttackedBy(brd, occ, G8, e, c) {
213215
return true
214216
}
215217
}
216218
}
217-
// fmt.Printf("Invalid castle move!{%s}. Castle rights: %d", m.ToString(), brd.castle)
218219
return false
219220
}
220-
case KNIGHT: // no special treatment needed for knights.
221-
221+
case KNIGHT:
222+
// no special treatment needed for knights.
222223
default:
223224
if slidingAttacks(piece, brd.AllOccupied(), from)&sqMaskOn[to] == 0 {
224-
// fmt.Printf("Invalid sliding attack!{%s}", m.ToString())
225225
return false
226226
}
227227
}

notes.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ Upgraded to Go 1.7
2727
Overhead: 45.4335m
2828
Timeout: 2.0s
2929
PASS
30+
31+
1/31/17, 2.9 GHz Core i5 (2x physical cores, 4 hyper-threads)
32+
Implemented memory recycling for move lists
33+
1034.6923m nodes searched in 408.7054s (2.5316m NPS)
34+
Total score: 289/300
35+
Overhead: 53.8827m
36+
Timeout: 2.0s

uci.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"fmt"
1717
"log"
1818
"os"
19+
"runtime"
1920
"strconv"
2021
"strings"
2122
"sync"
@@ -254,7 +255,7 @@ func (uci *UCIAdapter) identify() {
254255
func (uci *UCIAdapter) option() { // option name option_name [ parameters ]
255256
// tells the GUI which parameters can be changed in the engine.
256257
uci.Send("option name Ponder type check default false\n")
257-
258+
uci.Send(fmt.Sprintf("option name CPU type spin default 0 min 1 max %d\n", runtime.NumCPU()))
258259
}
259260

260261
// some example options from Toga 1.3.1:
@@ -302,6 +303,20 @@ func (uci *UCIAdapter) setOption(uciFields []string) {
302303
uci.invalid(uciFields)
303304
}
304305
}
306+
// option name CPU type spin default 0 min 1 max numCPU
307+
case "CPU":
308+
if len(uciFields) == 3 {
309+
numCPU, err := strconv.Atoi(uciFields[2])
310+
if err != nil {
311+
uci.invalid(uciFields)
312+
return
313+
}
314+
// fmt.Printf("setting up load balancer for %d CPU", numCPU)
315+
if numCPU > 0 && runtime.NumCPU() > numCPU {
316+
setupLoadBalancer(numCPU)
317+
// runtime.GC()
318+
}
319+
}
305320
default:
306321
}
307322
}

worker.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ type Worker struct {
3434
searchOverhead int
3535

3636
spList SPList
37-
stk Stack
37+
stk Stack
3838

3939
assignSp chan *SplitPoint
4040

41-
ptt *PawnTT
42-
recycler *Recycler
41+
ptt *PawnTT
42+
recycler *Recycler
4343
currentSp *SplitPoint
4444

4545
mask uint8
@@ -99,7 +99,6 @@ func (w *Worker) Help(b *Balancer) {
9999
go func() {
100100
var bestSp *SplitPoint
101101
for {
102-
103102
bestSp = nil
104103
for _, master := range b.workers { // try to find a good SP
105104
if master.index == w.index {
@@ -115,7 +114,7 @@ func (w *Worker) Help(b *Balancer) {
115114
}
116115

117116
if bestSp == nil || bestSp.WorkerFinished() { // No best SP was available.
118-
b.done <- w // Worker is completely idle and available to help any processor.
117+
b.done <- w // Worker is completely idle and available to help any processor.
119118
bestSp = <-w.assignSp // Wait for the next SP to be discovered.
120119
} else {
121120
bestSp.AddServant(w.mask)

0 commit comments

Comments
 (0)