gnugo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnugo-devel] do_remove_string() and update_liberties()


From: Paul Pogonyshev
Subject: [gnugo-devel] do_remove_string() and update_liberties()
Date: Mon, 30 Jun 2003 01:45:31 +0000
User-agent: KMail/1.5.9

here is yet one more speed optimization in board.c.

- do_remove_string() now does some job of update_liberties()
  (speed optimization)

i have also patched up a thin place in do_play_move() which went in
with Arend's fix of a bug in one of my previous speed optimization
patches.  it was an open doors for bugs in incremental board code and
i spent half an hour trying to understand why correct code caused
assertion failures.

profile results on nngs.tst:

before:
  1.32    603.44    12.80 45442922     0.00     0.00  update_liberties
  0.52    814.84     5.07 173278879     0.00     0.00  popgo
  0.28    877.36     2.74 20327540     0.00     0.00  do_remove_string
-----------------------------------------------
                2.74   16.84 20327540/20327540     do_play_move [65]
[126]    2.0    2.74   16.84 20327540         do_remove_string [126]
               12.80    0.00 45442162/45442922     update_liberties [149]
                2.73    0.00 45442162/137484513     remove_neighbor [170]
                1.31    0.00 30206150/203500012     hashdata_invert_stone [166]
-----------------------------------------------


after:
  0.50    801.82     4.77 173065842     0.00     0.00  popgo
  0.49    806.50     4.68 20272467     0.00     0.00  do_remove_string
  0.24    883.94     2.33  7029309     0.00     0.00  update_liberties
-----------------------------------------------
                4.68    6.06 20272467/20272467     do_play_move [73]
[155]    1.1    4.68    6.06 20272467         do_remove_string [155]
                2.63    0.00 45327566/137097312     remove_neighbor [169]
                2.33    0.00 7028533/7029309     update_liberties [236]
                1.10    0.00 30091969/203172794     hashdata_invert_stone [173]
-----------------------------------------------

total runtime per gprof:
before: 971.18
after:  955.55

note that the number of calls to different functions has changed
somewhat.  that is because liberties in board structures are now
often listed in different order.  this also explains why speed up
in total time seems to be larger than 0.9%.

i'm running regressions now.  there are no changes in the first 3 batches.

Paul


Index: engine/board.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/board.c,v
retrieving revision 1.77
diff -u -p -r1.77 board.c
--- engine/board.c      26 Jun 2003 20:24:03 -0000      1.77
+++ engine/board.c      29 Jun 2003 21:12:36 -0000
@@ -3892,6 +3892,7 @@ do_remove_string(int s)
 {
   int pos;
   int k;
+  int size = string[s].size;
 
   /* Traverse the stones of the string, by following the cyclic chain. */
   pos = FIRST_STONE(s);
@@ -3904,22 +3905,61 @@ do_remove_string(int s)
   } while (!BACK_TO_FIRST_STONE(s, pos));
 
   /* The neighboring strings have obtained some new liberties and lost
-   * a neighbor.
+   * a neighbor.  For speed reasons we handle two most common cases
+   * when string size is 1 or 2 stones here instead of calling
+   * update_liberties().
    */
-  for (k = 0; k < string[s].neighbors; k++) {
-    remove_neighbor(string[s].neighborlist[k], s);
-    update_liberties(string[s].neighborlist[k]);
+  if (size == 1) {
+    for (k = 0; k < string[s].neighbors; k++) {
+      int neighbor = string[s].neighborlist[k];
+
+      remove_neighbor(neighbor, s);
+      PUSH_VALUE(string[neighbor].liberties);
+
+      if (string[neighbor].liberties < MAX_LIBERTIES)
+       string[neighbor].libs[string[neighbor].liberties] = pos;
+      string[neighbor].liberties++;
+    }
+  }
+  else if (size == 2) {
+    int other = OTHER_COLOR(string[s].color);
+    int pos2 = NEXT_STONE(pos);
+
+    for (k = 0; k < string[s].neighbors; k++) {
+      int neighbor = string[s].neighborlist[k];      
+
+      remove_neighbor(neighbor, s);
+      PUSH_VALUE(string[neighbor].liberties);
+
+      if (NEIGHBOR_OF_STRING(pos, neighbor, other)) {
+       if (string[neighbor].liberties < MAX_LIBERTIES)
+         string[neighbor].libs[string[neighbor].liberties] = pos;
+       string[neighbor].liberties++;
+      }
+
+      if (NEIGHBOR_OF_STRING(pos2, neighbor, other)) {
+       if (string[neighbor].liberties < MAX_LIBERTIES)
+         string[neighbor].libs[string[neighbor].liberties] = pos2;
+       string[neighbor].liberties++;
+      }
+    }
+  }
+  else {
+    for (k = 0; k < string[s].neighbors; k++) {
+      remove_neighbor(string[s].neighborlist[k], s);
+      update_liberties(string[s].neighborlist[k]);
+    }
   }
 
   /* Update the number of captured stones. These are assumed to
    * already have been pushed.
    */
   if (string[s].color == WHITE)
-    white_captured += string[s].size;
+    white_captured += size;
   else
-    black_captured += string[s].size;
-    
-  return string[s].size;
+    black_captured += size;
+
+  return size;
 }
 
 
@@ -4350,8 +4390,12 @@ do_play_move(int pos, int color)
   /* Clear string mark. */
   string_mark++;
 
-  /* Put down the stone. */
+  /* Put down the stone.  We also set its string number to -1 for a while
+   * so that NEIGHBOR_OF_STRING() and friends don't get confused with the
+   * stone.
+   */
   DO_ADD_STONE(pos, color);
+  string_number[pos] = -1;
 
   /* Look in all directions. Count the number of neighbor strings of the same
    * color, remove captured strings and remove `pos' as liberty for opponent




reply via email to

[Prev in Thread] Current Thread [Next in Thread]