SlideShare a Scribd company logo
PLAYING GO
WITH CLOJURE

   Zach Tellman
    @ztellman
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
RULES OF GO
SHALL WE PLAY A GAME?
MY QUALIFICATIONS


• I’m    a mediocre Go player

•I   think this stuff is pretty cool

• I’ve   written performance-oriented Clojure before
THE GAME TREE



          X           X       X
                                  …



X O   X       O   X
                  O       …
THE GAME TREE



          X           X       X
                                  …



X O   X       O   X
                  O       …
THE GAME TREE



   a cooperative or single-player game, we only need to
• in
 search for victory

• in   a competitive game, we need to optimize for victory
MINIMAX


• assign   a value to each leaf node

       the parent the maximal child value if it’s our turn,
• assign
 or the minimal child value if it’s our opponent’s turn

• ascend    one level, and repeat
MINIMAX


• plays   a perfect game

• requires   traversing the entire tree

• there   are ~9! possible tic-tac-toe games
EVALUATION FUNCTIONS


• construct    a shallow game tree

       each leaf node a value based on our best guess at
• assign
 the outcome

• apply    minimax to these values
THE TROUBLE
             WITH HEURISTICS

• difficult   to quantify

• depth   vs. quality

• understanding a function vs. understanding its repeated,
 recursive application
THE TROUBLE
                     WITH GO


• lots   of breadth

• lots   of depth
HISTORICAL APPROACHES



• programmers     who are professional-level players

• shallow   and narrow searches, heavy evaluation functions
MONTE CARLO SIMULATION
MONTE CARLO SIMULATION

             (defn inside-circle? [x y]
               (>= 1 (+ (* x x) (* y y))))

             (defn sample []
               (inside-circle? (rand) (rand)))
1




    (0,0)
MONTE CARLO SIMULATION

             (defn inside-circle? [x y]
               (>= 1 (+ (* x x) (* y y))))

             (defn sample []
               (inside-circle? (rand) (rand)))
1




             (repeatedly 1e6 sample)
    (0,0)
MONTE CARLO SIMULATION
MONTE CARLO EVALUATION


• thestrength of a position is how often one side wins,
 given repeated, naive playouts by both sides

• possible   playouts vs plausible playouts

• eachnew playout gives us additional information about
 what is plausible
MULTI-ARMED BANDIT
MULTI-ARMED BANDIT


• multiple   levers to pull, each with an unknown expected
  reward

• exploitation   vs exploration

• if
   the search space is stable over time, we expect to
  converge on a solution
MONTE CARLO TREE SEARCH
SIMULATING GO
                WITH CLOJURE

• select   a move

• check    for suicide

• make     move

• check    for capture

• repeat
SIMULATING GO
               WITH CLOJURE

• select   a move

•   check for suicide

• make     move

•   check for capture

• repeat
Playing Go with Clojure
INCREMENTAL STATE




           4
INCREMENTAL STATE


           6
INCREMENTAL STATE


        8
INCREMENTAL STATE


        6

        2
INCREMENTAL STATE


• we  keep track of the pseudo-liberties, but also the
  neighbor sum and sum-of-squares

• ifsum × sum = psudeo-liberties × sum-of-squares,
  there’s only one real liberty

• proof   is left as an exercise for the reader
A LITTLE ARITHMETIC

• select   a move        1 second
                         / 10,000 games per second
• check    for suicide

• make     move

• check    for capture

• repeat
A LITTLE ARITHMETIC

• select   a move        1 second
                         / 10,000 games per second
• check    for suicide   / 100 moves per game

• make     move

• check    for capture

• repeat
A LITTLE ARITHMETIC

• select   a move        1 second
                         / 10,000 games per second
• check    for suicide   / 100 moves per game

• make     move

• check    for capture

• repeat                 = 1μs per move
A MILLION TIMES
         A SECOND

(assoc {} :a 1, :b 2, :c 3, :d 4, :e 5)



(reduce + (range 10))



(set (range 5))
execute typical instruction           1 ns

fetch from L1 cache memory          0.5 ns

branch misprediction                  5 ns

fetch from L2 cache memory            7 ns

mutex lock/unlock                   25 ns

fetch from main memory             100 ns



     “Teach Yourself Programming in Ten Years”
                           Peter Norvig, 2001
execute typical instruction           1 ns

fetch from L1 cache memory          0.5 ns

branch misprediction                  5 ns

fetch from L2 cache memory            7 ns

mutex lock/unlock                   25 ns

fetch from main memory             100 ns



     “Teach Yourself Programming in Ten Years”
                           Peter Norvig, 2001
A QUICK DESCENT
      INTO
   INSANITY
 PERFORMANCE
NOT YOUR DAY JOB


• not   latency bound

• faster   is smarter

• diminishing   returns not within reach
MUTABLE STATE


“They are for experts only - if the semantics and
 implications of :volatile-mutable or :unsynchronized-
 mutable are not immediately apparent to you, you
 should not be using them.”


                                      Rich Hickey,
                         the docstring for deftype
MUTABLE STATE
MUTABLE STATE


• if
   a value is only used on a single thread, it can be
  unsynchronized

• for   everything else, use volatile

• unsynchronized     is roughly 2x faster
MUTABLE STATE
(deftype Mutable
  [^:unsynchronized-mutable ^long counter]

  IMutable
  (get-counter [_]
    counter)
  (set-counter [_ val]
    (set! counter val)))
MUTABLE STATE
(deftype Mutable
  [^:unsynchronized-mutable ^long counter]

  IMutable
  (get-counter [_]
    counter)
  (set-counter [_ val]
    (set! counter val)))

(defn add [^Mutable m ^long val]
  (set-counter m (+ (get-counter m) val)))
MUTABLE STATE
(deftype Mutable
  [^:unsynchronized-mutable ^long counter]

  IMutable
  (get-counter [_]
    counter)
  (set-counter [_ val]
    (set! counter val))
  (add [_ val]
    (set! counter (+ counter val))))
MEASURE TWICE,
            CODE ONCE
user> (bench (assoc {} :a 1, :b 2, :c 3, :d 4, :e 5))

Evaluation count : 46619100 in 60 samples of 776985 calls.

           Execution time mean   :   1.286463   us
  Execution time std-deviation   :   4.220920   ns
 Execution time lower quantile   :   1.280215   us ( 2.5%)
 Execution time upper quantile   :   1.295557   us (97.5%)

Found 4 outliers in 60 samples (6.6667 %)
    low-severe   1 (1.6667 %)
    low-mild     2 (3.3333 %)
    high-mild    1 (1.6667 %)
 Variance from outliers : 1.6389 %
CRITERIUM


• one   of the many great libraries from Hugo Duncan

• use   it at the REPL, and in your tests

• tends   to exaggerate cache coherency

• minimum     resolution appears to be ~15ns
BOTTOM-UP PERFORMANCE


• measure   each piece of your code

• measure   them when used together

• buildan intuition for how long something should take,
 and investigate when you’re wrong
INDIRECTION


“Any performance problem can be solved
 by removing a layer of indirection.”

                            Unattributed
INDIRECTION


     =                    count



==       identical?   Array/getLength
INDIRECTION
PUT IT ALL TOGETHER
> lein test pushkin.test.simulator :benchmark

-----
 random 9x9 playout
-----

Evaluation count : 501120 in 60 samples of 8352 calls.
             Execution time mean : 121.293385 us
    Execution time std-deviation : 2.534460 us
   Execution time lower quantile : 119.685345 us ( 2.5%)
   Execution time upper quantile : 128.150772 us (97.5%)

Found 8 outliers in 60 samples (13.3333 %)
    low-severe   3 (5.0000 %)
    low-mild     5 (8.3333 %)
 Variance from outliers : 9.4036 %
PUT IT ALL TOGETHER
> lein test pushkin.test.simulator :benchmark

-----
 random 9x9 playout
-----

Evaluation count : 501120 in 60 samples of 8352 calls.
             Execution time mean : 121.293385 us
    Execution time std-deviation : 2.534460 us
   Execution time lower quantile : 119.685345 us ( 2.5%)
   Execution time upper quantile : 128.150772 us (97.5%)

Found 8 outliers in 60 samples (13.3333 %)
    low-severe   3 (5.0000 %)
    low-mild     5 (8.3333 %)
 Variance from outliers : 9.4036 %
PLUMBING THE DEPTHS
      OF PERFORMANCE
          INSANITY
• simulating   C-style structs with ByteBuffers

• mimicking    C compiler offset calculation with local analysis

• creating   a bridge to heterogeneous computing
Exploitation             Strong AIs




               Pushkin
Exploration
           Possible          Plausible




    http://github.com/ztellman/pushkin
Playing Go with Clojure
QUESTIONS?

More Related Content

PPTX
Transferring Software Testing and Analytics Tools to Practice
PPT
Artificial intelligence games
PPT
AI.ppt
PPT
artificial intelligence and Game development
PDF
Melbourne, Australia Global Day of Code Retreat 2018 gdcr18 - Event Slides
PDF
Transferring Software Testing Tools to Practice (AST 2017 Keynote)
PDF
Learn Dynamic Programming Roadmap at Tutort Academy
Transferring Software Testing and Analytics Tools to Practice
Artificial intelligence games
AI.ppt
artificial intelligence and Game development
Melbourne, Australia Global Day of Code Retreat 2018 gdcr18 - Event Slides
Transferring Software Testing Tools to Practice (AST 2017 Keynote)
Learn Dynamic Programming Roadmap at Tutort Academy

Similar to Playing Go with Clojure (20)

PDF
Elements of Programming Interviews.pdf
DOC
Time and space complexity
PPTX
CptS 440 / 540 Artificial Intelligence
DOCX
Divide-and-Conquer & Dynamic ProgrammingDivide-and-Conqu.docx
PDF
Algorithms
PPTX
Approaches to game AI overview
PPT
Testing
PPT
AutoTest.ppt
PPT
AutoTest.ppt
PPT
AutoTest.ppt
PDF
On the value of stochastic analysis for software engineering
PDF
02 analysis
PPT
DOCX
Searching techniques
PDF
Parallel search
PDF
Deterministic Simulation - What modern online games can learn from the Game B...
PDF
AI Lab menu for ptu students and easy to use and best quality and help for 6t...
PDF
Skiena algorithm 2007 lecture18 application of dynamic programming
PDF
Introduction to computing Processing and performance.pdf
PPTX
Applied Algorithms Introduction to Algorithms.pptx
Elements of Programming Interviews.pdf
Time and space complexity
CptS 440 / 540 Artificial Intelligence
Divide-and-Conquer & Dynamic ProgrammingDivide-and-Conqu.docx
Algorithms
Approaches to game AI overview
Testing
AutoTest.ppt
AutoTest.ppt
AutoTest.ppt
On the value of stochastic analysis for software engineering
02 analysis
Searching techniques
Parallel search
Deterministic Simulation - What modern online games can learn from the Game B...
AI Lab menu for ptu students and easy to use and best quality and help for 6t...
Skiena algorithm 2007 lecture18 application of dynamic programming
Introduction to computing Processing and performance.pdf
Applied Algorithms Introduction to Algorithms.pptx
Ad

Recently uploaded (20)

PDF
Encapsulation theory and applications.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
Cloud computing and distributed systems.
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Approach and Philosophy of On baking technology
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
KodekX | Application Modernization Development
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
Big Data Technologies - Introduction.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Encapsulation theory and applications.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Diabetes mellitus diagnosis method based random forest with bat algorithm
Cloud computing and distributed systems.
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Understanding_Digital_Forensics_Presentation.pptx
The Rise and Fall of 3GPP – Time for a Sabbatical?
Approach and Philosophy of On baking technology
Spectral efficient network and resource selection model in 5G networks
KodekX | Application Modernization Development
NewMind AI Weekly Chronicles - August'25 Week I
Programs and apps: productivity, graphics, security and other tools
Big Data Technologies - Introduction.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Ad

Playing Go with Clojure

  • 1. PLAYING GO WITH CLOJURE Zach Tellman @ztellman
  • 20. SHALL WE PLAY A GAME?
  • 21. MY QUALIFICATIONS • I’m a mediocre Go player •I think this stuff is pretty cool • I’ve written performance-oriented Clojure before
  • 22. THE GAME TREE X X X … X O X O X O …
  • 23. THE GAME TREE X X X … X O X O X O …
  • 24. THE GAME TREE a cooperative or single-player game, we only need to • in search for victory • in a competitive game, we need to optimize for victory
  • 25. MINIMAX • assign a value to each leaf node the parent the maximal child value if it’s our turn, • assign or the minimal child value if it’s our opponent’s turn • ascend one level, and repeat
  • 26. MINIMAX • plays a perfect game • requires traversing the entire tree • there are ~9! possible tic-tac-toe games
  • 27. EVALUATION FUNCTIONS • construct a shallow game tree each leaf node a value based on our best guess at • assign the outcome • apply minimax to these values
  • 28. THE TROUBLE WITH HEURISTICS • difficult to quantify • depth vs. quality • understanding a function vs. understanding its repeated, recursive application
  • 29. THE TROUBLE WITH GO • lots of breadth • lots of depth
  • 30. HISTORICAL APPROACHES • programmers who are professional-level players • shallow and narrow searches, heavy evaluation functions
  • 32. MONTE CARLO SIMULATION (defn inside-circle? [x y] (>= 1 (+ (* x x) (* y y)))) (defn sample [] (inside-circle? (rand) (rand))) 1 (0,0)
  • 33. MONTE CARLO SIMULATION (defn inside-circle? [x y] (>= 1 (+ (* x x) (* y y)))) (defn sample [] (inside-circle? (rand) (rand))) 1 (repeatedly 1e6 sample) (0,0)
  • 35. MONTE CARLO EVALUATION • thestrength of a position is how often one side wins, given repeated, naive playouts by both sides • possible playouts vs plausible playouts • eachnew playout gives us additional information about what is plausible
  • 37. MULTI-ARMED BANDIT • multiple levers to pull, each with an unknown expected reward • exploitation vs exploration • if the search space is stable over time, we expect to converge on a solution
  • 39. SIMULATING GO WITH CLOJURE • select a move • check for suicide • make move • check for capture • repeat
  • 40. SIMULATING GO WITH CLOJURE • select a move • check for suicide • make move • check for capture • repeat
  • 46. INCREMENTAL STATE • we keep track of the pseudo-liberties, but also the neighbor sum and sum-of-squares • ifsum × sum = psudeo-liberties × sum-of-squares, there’s only one real liberty • proof is left as an exercise for the reader
  • 47. A LITTLE ARITHMETIC • select a move 1 second / 10,000 games per second • check for suicide • make move • check for capture • repeat
  • 48. A LITTLE ARITHMETIC • select a move 1 second / 10,000 games per second • check for suicide / 100 moves per game • make move • check for capture • repeat
  • 49. A LITTLE ARITHMETIC • select a move 1 second / 10,000 games per second • check for suicide / 100 moves per game • make move • check for capture • repeat = 1μs per move
  • 50. A MILLION TIMES A SECOND (assoc {} :a 1, :b 2, :c 3, :d 4, :e 5) (reduce + (range 10)) (set (range 5))
  • 51. execute typical instruction 1 ns fetch from L1 cache memory 0.5 ns branch misprediction 5 ns fetch from L2 cache memory 7 ns mutex lock/unlock 25 ns fetch from main memory 100 ns “Teach Yourself Programming in Ten Years” Peter Norvig, 2001
  • 52. execute typical instruction 1 ns fetch from L1 cache memory 0.5 ns branch misprediction 5 ns fetch from L2 cache memory 7 ns mutex lock/unlock 25 ns fetch from main memory 100 ns “Teach Yourself Programming in Ten Years” Peter Norvig, 2001
  • 53. A QUICK DESCENT INTO INSANITY PERFORMANCE
  • 54. NOT YOUR DAY JOB • not latency bound • faster is smarter • diminishing returns not within reach
  • 55. MUTABLE STATE “They are for experts only - if the semantics and implications of :volatile-mutable or :unsynchronized- mutable are not immediately apparent to you, you should not be using them.” Rich Hickey, the docstring for deftype
  • 57. MUTABLE STATE • if a value is only used on a single thread, it can be unsynchronized • for everything else, use volatile • unsynchronized is roughly 2x faster
  • 58. MUTABLE STATE (deftype Mutable [^:unsynchronized-mutable ^long counter] IMutable (get-counter [_] counter) (set-counter [_ val] (set! counter val)))
  • 59. MUTABLE STATE (deftype Mutable [^:unsynchronized-mutable ^long counter] IMutable (get-counter [_] counter) (set-counter [_ val] (set! counter val))) (defn add [^Mutable m ^long val] (set-counter m (+ (get-counter m) val)))
  • 60. MUTABLE STATE (deftype Mutable [^:unsynchronized-mutable ^long counter] IMutable (get-counter [_] counter) (set-counter [_ val] (set! counter val)) (add [_ val] (set! counter (+ counter val))))
  • 61. MEASURE TWICE, CODE ONCE user> (bench (assoc {} :a 1, :b 2, :c 3, :d 4, :e 5)) Evaluation count : 46619100 in 60 samples of 776985 calls. Execution time mean : 1.286463 us Execution time std-deviation : 4.220920 ns Execution time lower quantile : 1.280215 us ( 2.5%) Execution time upper quantile : 1.295557 us (97.5%) Found 4 outliers in 60 samples (6.6667 %) low-severe 1 (1.6667 %) low-mild 2 (3.3333 %) high-mild 1 (1.6667 %) Variance from outliers : 1.6389 %
  • 62. CRITERIUM • one of the many great libraries from Hugo Duncan • use it at the REPL, and in your tests • tends to exaggerate cache coherency • minimum resolution appears to be ~15ns
  • 63. BOTTOM-UP PERFORMANCE • measure each piece of your code • measure them when used together • buildan intuition for how long something should take, and investigate when you’re wrong
  • 64. INDIRECTION “Any performance problem can be solved by removing a layer of indirection.” Unattributed
  • 65. INDIRECTION = count == identical? Array/getLength
  • 67. PUT IT ALL TOGETHER > lein test pushkin.test.simulator :benchmark ----- random 9x9 playout ----- Evaluation count : 501120 in 60 samples of 8352 calls. Execution time mean : 121.293385 us Execution time std-deviation : 2.534460 us Execution time lower quantile : 119.685345 us ( 2.5%) Execution time upper quantile : 128.150772 us (97.5%) Found 8 outliers in 60 samples (13.3333 %) low-severe 3 (5.0000 %) low-mild 5 (8.3333 %) Variance from outliers : 9.4036 %
  • 68. PUT IT ALL TOGETHER > lein test pushkin.test.simulator :benchmark ----- random 9x9 playout ----- Evaluation count : 501120 in 60 samples of 8352 calls. Execution time mean : 121.293385 us Execution time std-deviation : 2.534460 us Execution time lower quantile : 119.685345 us ( 2.5%) Execution time upper quantile : 128.150772 us (97.5%) Found 8 outliers in 60 samples (13.3333 %) low-severe 3 (5.0000 %) low-mild 5 (8.3333 %) Variance from outliers : 9.4036 %
  • 69. PLUMBING THE DEPTHS OF PERFORMANCE INSANITY • simulating C-style structs with ByteBuffers • mimicking C compiler offset calculation with local analysis • creating a bridge to heterogeneous computing
  • 70. Exploitation Strong AIs Pushkin Exploration Possible Plausible http://github.com/ztellman/pushkin

Editor's Notes