gnugo-devel
[Top][All Lists]
Advanced

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

[gnugo-devel] MAX_LIBERTIES


From: Arend Bayer
Subject: [gnugo-devel] MAX_LIBERTIES
Date: Tue, 16 Nov 2004 20:31:18 +0100 (CET)

Triggered by Anders Kierulf's remark on MAX_LIBERTIES, I tried two
things: Reducing it (to improve cache locality), or removing it (thus
simplifying the code and removing a lot of branches).

Reducing it to 8 gave a speedup of almost 1%. Removing it (as in the
preliminary patch below) cost about 0.1% compared to the current
situation.

So question: Do we rather want slightly easier code or 1% performance
gain?

Arend


Index: engine/board.c
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/board.c,v
retrieving revision 1.103
diff -u -p -r1.103 board.c
--- engine/board.c      13 Nov 2004 04:46:43 -0000      1.103
+++ engine/board.c      16 Nov 2004 19:33:12 -0000
@@ -247,15 +247,13 @@ static int next_stone[BOARDMAX];
 
 #define ADD_LIBERTY(s, pos)\
   do {\
-    if (string[s].liberties < MAX_LIBERTIES)\
-      string[s].libs[string[s].liberties] = pos;\
+    string[s].libs[string[s].liberties] = pos;\
     string[s].liberties++;\
   } while (0)
 
 #define ADD_AND_MARK_LIBERTY(s, pos)\
   do {\
-    if (string[s].liberties < MAX_LIBERTIES)\
-      string[s].libs[string[s].liberties] = pos;\
+    string[s].libs[string[s].liberties] = pos;\
     string[s].liberties++;\
     ml[pos] = liberty_mark;\
   } while (0)
@@ -1403,63 +1401,17 @@ findlib(int str, int maxlib, int *libs)
   
   /* We already have the list of liberties and only need to copy it to
    * libs[].
-   *
-   * However, if the string has more than MAX_LIBERTIES liberties the
-   * list is truncated and if maxlib is also larger than MAX_LIBERTIES
-   * we have to traverse the stones in the string in order to find
-   * where the liberties are.
    */
   s = string_number[str];
   liberties = string[s].liberties;
+  maxlib = gg_min(liberties, maxlib);
 
-  if (liberties <= MAX_LIBERTIES || maxlib <= MAX_LIBERTIES) {
-    /* The easy case, it suffices to copy liberty locations from the
-     * incrementally updated list.
-     */
-    for (k = 0; k < maxlib && k < liberties; k++)
-      libs[k] = string[s].libs[k];
-  }
-  else {
-    /* The harder case, where we have to traverse the stones in the
-     * string. We don't have to check explicitly if we are back to
-     * the start of the chain since we will run out of liberties
-     * before that happens.
-     */
-    int pos;
-    liberty_mark++;
-    for (k = 0, pos = FIRST_STONE(s);
-        k < maxlib && k < liberties;
-        pos = NEXT_STONE(pos)) {
-      if (UNMARKED_LIBERTY(SOUTH(pos))) {
-       libs[k++] = SOUTH(pos);
-       MARK_LIBERTY(SOUTH(pos));
-       if (k >= maxlib)
-         break;
-      }
-      
-      if (UNMARKED_LIBERTY(WEST(pos))) {
-       libs[k++] = WEST(pos);
-       MARK_LIBERTY(WEST(pos));
-       if (k >= maxlib)
-         break;
-      }
-      
-      if (UNMARKED_LIBERTY(NORTH(pos))) {
-       libs[k++] = NORTH(pos);
-       MARK_LIBERTY(NORTH(pos));
-       if (k >= maxlib)
-         break;
-      }
-      
-      if (UNMARKED_LIBERTY(EAST(pos))) {
-       libs[k++] = EAST(pos);
-       MARK_LIBERTY(EAST(pos));
-       if (k >= maxlib)
-         break;
-      }
-    }
-  }
-      
+  /* The easy case, it suffices to copy liberty locations from the
+   * incrementally updated list.
+   */
+  for (k = 0; k < maxlib; k++)
+    libs[k] = string[s].libs[k];
+    
   return liberties;
 }
 
@@ -1708,10 +1660,7 @@ approxlib(int pos, int color, int maxlib
    */
   entry->threshold = maxlib;
 
-  if (maxlib <= MAX_LIBERTIES)
-    liberties = do_approxlib(pos, color, maxlib, libs);
-  else
-    liberties = slow_approxlib(pos, color, maxlib, libs);
+  liberties = do_approxlib(pos, color, maxlib, libs);
 
   entry->liberties = liberties;
   entry->position_hash = board_hash;
@@ -1727,10 +1676,7 @@ approxlib(int pos, int color, int maxlib
       return liberties;
   }
 
-  if (maxlib <= MAX_LIBERTIES)
-    liberties = do_approxlib(pos, color, maxlib, libs);
-  else
-    liberties = slow_approxlib(pos, color, maxlib, libs);
+  liberties = do_approxlib(pos, color, maxlib, libs);
 
 #endif /* not USE_BOARD_CACHES */
 
@@ -1746,14 +1692,9 @@ do_approxlib(int pos, int color, int max
   int liberties = 0;
 
   /* Look for empty neighbors and the liberties of the adjacent
-   * strings of the given color. The algorithm below won't work
-   * correctly if any of the adjacent strings have more than
-   * MAX_LIBERTIES liberties AND maxlib is larger than MAX_LIBERTIES.
-   * therefore approxlib() calls more robust slow_approxlib() if
-   * this might be the case.
-   */
-
-  /* Start by marking pos itself so it isn't counted among its own
+   * strings of the given color.
+   *
+   * Start by marking pos itself so it isn't counted among its own
    * liberties.
    */
   liberty_mark++;
@@ -2058,76 +1999,21 @@ do_accuratelib(int pos, int color, int m
       /* An own neighbor string */
       struct string_data *s = &string[string_number[pos2]];
 
-      if (s->liberties <= MAX_LIBERTIES || maxlib <= MAX_LIBERTIES - 1) {
-       /* The easy case - we already have all (necessary) liberties of
-        * the string listed
-        */
-       for (l = 0; l < s->liberties; l++) {
-         lib = s->libs[l];
-         if (UNMARKED_LIBERTY(lib)) {
-           if (libs)
-             libs[liberties] = lib;
-           liberties++;
-           if (liberties >= maxlib)
-             return liberties;
+      /* The easy case - we already have all (necessary) liberties of
+       * the string listed
+       */
+      for (l = 0; l < s->liberties; l++) {
+       lib = s->libs[l];
+       if (UNMARKED_LIBERTY(lib)) {
+         if (libs)
+           libs[liberties] = lib;
+         liberties++;
+         if (liberties >= maxlib)
+           return liberties;
 
-           MARK_LIBERTY(lib);
-         }
+         MARK_LIBERTY(lib);
        }
       }
-      else {
-       /* The harder case - we need to find all the liberties of the
-        * string by traversing its stones. We stop as soon as we have
-        * traversed all the stones or have reached maxlib. Unfortunately,
-        * we cannot use the trick from findlib() since some of the
-        * liberties may already have been marked.
-        */
-       int stone = pos2;
-       do {
-         if (UNMARKED_LIBERTY(SOUTH(stone))) {
-           if (libs)
-             libs[liberties] = SOUTH(stone);
-           liberties++;
-           if (liberties >= maxlib)
-             return liberties;
-
-           MARK_LIBERTY(SOUTH(stone));
-         }
-
-         if (UNMARKED_LIBERTY(WEST(stone))) {
-           if (libs)
-             libs[liberties] = WEST(stone);
-           liberties++;
-           if (liberties >= maxlib)
-             return liberties;
-
-           MARK_LIBERTY(WEST(stone));
-         }
-
-         if (UNMARKED_LIBERTY(NORTH(stone))) {
-           if (libs)
-             libs[liberties] = NORTH(stone);
-           liberties++;
-           if (liberties >= maxlib)
-             return liberties;
-
-           MARK_LIBERTY(NORTH(stone));
-         }
-
-         if (UNMARKED_LIBERTY(EAST(stone))) {
-           if (libs)
-             libs[liberties] = EAST(stone);
-           liberties++;
-           if (liberties >= maxlib)
-             return liberties;
-
-           MARK_LIBERTY(EAST(stone));
-         }
-
-         stone = NEXT_STONE(stone);
-       } while (stone != pos2);
-      }
-
       MARK_STRING(pos2);
     }
     else if (board[pos2] == OTHER_COLOR(color)
@@ -2193,7 +2079,7 @@ do_accuratelib(int pos, int color, int m
 int
 count_common_libs(int str1, int str2)
 {
-  int all_libs1[MAXLIBS], *libs1;
+  int *libs1;
   int liberties1, liberties2;
   int commonlibs = 0;
   int k, n, tmp;
@@ -2214,36 +2100,22 @@ count_common_libs(int str1, int str2)
     str2 = tmp;
   }
 
-  if (liberties1 <= MAX_LIBERTIES) {
-    /* Speed optimization: don't copy liberties with findlib */
-    libs1 = string[n].libs;
-    n = string_number[str2];
-    liberties2 = string[n].liberties;
-    
-    if (liberties2 <= MAX_LIBERTIES) {
-      /* Speed optimization: NEIGHBOR_OF_STRING is quite expensive */
-      liberty_mark++;
-      
-      for (k = 0; k < liberties1; k++)
-       MARK_LIBERTY(libs1[k]);
-
-      libs1 = string[n].libs;
-      for (k = 0; k < liberties2; k++)
-       if (!UNMARKED_LIBERTY(libs1[k]))
-         commonlibs++;
-
-      return commonlibs;
-    }
-  }
-  else {
-    findlib(str1, MAXLIBS, all_libs1);
-    libs1 = all_libs1;
-  }
+  /* Speed optimization: don't copy liberties with findlib */
+  libs1 = string[n].libs;
+  n = string_number[str2];
+  liberties2 = string[n].liberties;
+  
+  /* Speed optimization: NEIGHBOR_OF_STRING is quite expensive */
+  liberty_mark++;
   
   for (k = 0; k < liberties1; k++)
-    if (NEIGHBOR_OF_STRING(libs1[k], string_number[str2], board[str2]))
+    MARK_LIBERTY(libs1[k]);
+
+  libs1 = string[n].libs;
+  for (k = 0; k < liberties2; k++)
+    if (!UNMARKED_LIBERTY(libs1[k]))
       commonlibs++;
-  
+
   return commonlibs;
 }
 
@@ -2260,7 +2132,7 @@ count_common_libs(int str1, int str2)
 int
 find_common_libs(int str1, int str2, int maxlib, int *libs)
 {
-  int all_libs1[MAXLIBS], *libs1;
+  int *libs1;
   int liberties1, liberties2;
   int commonlibs = 0;
   int k, n, tmp;
@@ -2282,37 +2154,20 @@ find_common_libs(int str1, int str2, int
     str2 = tmp;
   }
   
-  if (liberties1 <= MAX_LIBERTIES) {
-    /* Speed optimization: don't copy liberties with findlib */
-    libs1 = string[n].libs;
-    n = string_number[str2];
-    liberties2 = string[n].liberties;
+  /* Speed optimization: don't copy liberties with findlib */
+  libs1 = string[n].libs;
+  n = string_number[str2];
+  liberties2 = string[n].liberties;
 
-    if (liberties2 <= MAX_LIBERTIES) {
-      /* Speed optimization: NEIGHBOR_OF_STRING is quite expensive */
-      liberty_mark++;
+  /* Speed optimization: NEIGHBOR_OF_STRING is quite expensive */
+  liberty_mark++;
 
-      for (k = 0; k < liberties1; k++)
-       MARK_LIBERTY(libs1[k]);
-      
-      libs1 = string[n].libs;
-      for (k = 0; k < liberties2; k++)
-       if (!UNMARKED_LIBERTY(libs1[k])) {
-          if (commonlibs < maxlib)
-           libs[commonlibs] = libs1[k];
-         commonlibs++;
-       }
-      
-      return commonlibs;
-    }
-  }
-  else {
-    findlib(str1, MAXLIBS, all_libs1);
-    libs1 = all_libs1;
-  }
-  
   for (k = 0; k < liberties1; k++)
-    if (NEIGHBOR_OF_STRING(libs1[k], string_number[str2], board[str2])) {
+    MARK_LIBERTY(libs1[k]);
+  
+  libs1 = string[n].libs;
+  for (k = 0; k < liberties2; k++)
+    if (!UNMARKED_LIBERTY(libs1[k])) {
       if (commonlibs < maxlib)
        libs[commonlibs] = libs1[k];
       commonlibs++;
@@ -2328,7 +2183,7 @@ find_common_libs(int str1, int str2, int
 int
 have_common_lib(int str1, int str2, int *lib)
 {
-  int all_libs1[MAXLIBS], *libs1;
+  int *libs1;
   int liberties1;
   int k, n, tmp;
   
@@ -2348,13 +2203,8 @@ have_common_lib(int str1, int str2, int 
     str2 = tmp;
   }
   
-  if (liberties1 <= MAX_LIBERTIES)
-    /* Speed optimization: don't copy liberties with findlib */
-    libs1 = string[n].libs;
-  else {
-    findlib(str1, MAXLIBS, all_libs1);
-    libs1 = all_libs1;
-  }
+  /* Speed optimization: don't copy liberties with findlib */
+  libs1 = string[n].libs;
 
   for (k = 0; k < liberties1; k++) {
     if (NEIGHBOR_OF_STRING(libs1[k], string_number[str2], board[str2])) {
@@ -3262,7 +3112,7 @@ update_liberties(int s)
 
   /* Push the old information. */
   PUSH_VALUE(string[s].liberties);
-  for (k = 0; k < string[s].liberties && k < MAX_LIBERTIES; k++) {
+  for (k = 0; k < string[s].liberties; k++) {
     PUSH_VALUE(string[s].libs[k]);
   }
   string[s].liberties = 0;
@@ -3335,22 +3185,18 @@ remove_liberty(int str_number, int pos)
   int k;
   struct string_data *s = &string[str_number];
   
-  if (s->liberties > MAX_LIBERTIES)
-    update_liberties(str_number);
-  else {
-    for (k = 0; k < s->liberties; k++)
-      if (s->libs[k] == pos) {
-       /* We need to push the last entry too because it may become
-        * destroyed later.
-        */
-       PUSH_VALUE(s->libs[s->liberties - 1]);
-       PUSH_VALUE(s->libs[k]);
-       PUSH_VALUE(s->liberties);
-       s->libs[k] = s->libs[s->liberties - 1];
-       s->liberties--;
-       break;
-      }
-  }
+  for (k = 0; k < s->liberties; k++)
+    if (s->libs[k] == pos) {
+      /* We need to push the last entry too because it may become
+       * destroyed later.
+       */
+      PUSH_VALUE(s->libs[s->liberties - 1]);
+      PUSH_VALUE(s->libs[k]);
+      PUSH_VALUE(s->liberties);
+      s->libs[k] = s->libs[s->liberties - 1];
+      s->liberties--;
+      break;
+    }
 }
 
 
@@ -3387,8 +3233,7 @@ do_remove_string(int s)
       remove_neighbor(neighbor, s);
       PUSH_VALUE(string[neighbor].liberties);
 
-      if (string[neighbor].liberties < MAX_LIBERTIES)
-       string[neighbor].libs[string[neighbor].liberties] = pos;
+      string[neighbor].libs[string[neighbor].liberties] = pos;
       string[neighbor].liberties++;
     }
   }
@@ -3403,14 +3248,12 @@ do_remove_string(int 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].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].libs[string[neighbor].liberties] = pos2;
        string[neighbor].liberties++;
       }
     }
@@ -3551,19 +3394,8 @@ extend_neighbor_string(int pos, int s)
   PUSH_VALUE(string[s].size);
   string[s].size++;
 
-  /* If s has too many liberties, we don't know where they all are and
-   * can't update the liberties with the algorithm we otherwise
-   * use. In that case we can only recompute the liberties from
-   * scratch.
-   */
-  if (string[s].liberties > MAX_LIBERTIES) {
-    update_liberties(s);
-    liberties_updated = 1;
-  }
-  else {
-    /* The place of the new stone is no longer a liberty. */
-    remove_liberty(s, pos);
-  }
+  /* The place of the new stone is no longer a liberty. */
+  remove_liberty(s, pos);
 
   /* Mark old neighbors of the string. */
   string_mark++;
@@ -3677,27 +3509,12 @@ assimilate_string(int s, int pos)
    * It is assumed that the liberties of s have been marked before
    * this function is called.
    */
-  if (string[s2].liberties <= MAX_LIBERTIES) {
-    for (k = 0; k < string[s2].liberties; k++) {
-      int pos2 = string[s2].libs[k];
-      if (UNMARKED_LIBERTY(pos2)) {
-       ADD_AND_MARK_LIBERTY(s, pos2);
-      }
+  for (k = 0; k < string[s2].liberties; k++) {
+    int pos2 = string[s2].libs[k];
+    if (UNMARKED_LIBERTY(pos2)) {
+      ADD_AND_MARK_LIBERTY(s, pos2);
     }
   }
-  else {
-    /* If s2 had too many liberties the above strategy wouldn't be
-     * effective, since not all liberties are listed in
-     * libs[] the chain of stones for s2 is no
-     * longer available (it has already been merged with s) so we
-     * can't reconstruct the s2 liberties. Instead we capitulate and
-     * rebuild the list of liberties for s (including the neighbor
-     * strings assimilated so far) from scratch.
-     */
-    liberty_mark++;          /* Reset the mark. */
-    string[s].liberties = 0; /* To avoid pushing the current list. */
-    update_liberties(s);
-  }
 
   /* Remove s2 as neighbor to the neighbors of s2 and instead add s if
    * they don't already have added it. Also add the neighbors of s2 as
Index: engine/board.h
===================================================================
RCS file: /cvsroot/gnugo/gnugo/engine/board.h,v
retrieving revision 1.17
diff -u -p -r1.17 board.h
--- engine/board.h      13 Nov 2004 04:46:43 -0000      1.17
+++ engine/board.h      16 Nov 2004 19:33:12 -0000
@@ -43,7 +43,7 @@
  */
 #define MAXLIBS   (2*(MAX_BOARD*MAX_BOARD + 1)/3)
 /* This is a smaller, practical number of liberties that we care to keep track 
of. */
-#define MAX_LIBERTIES 20
+#define MAX_LIBERTIES MAXLIBS
 
 
 /* This is an upper bound of the number of strings that can exist on





reply via email to

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