Subversion Repositories Games.Chess Giants

Rev

Rev 154 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
108 pmbaty 1
#include "chess.h"
2
#include "data.h"
3
/* last modified 08/26/15 */
4
/*
5
 *******************************************************************************
6
 *                                                                             *
7
 *   AutoTune() is used to tune the parallel search parameters and optimize    *
8
 *   them for the current hardware and a specific time per move target.  The   *
9
 *   syntax of the command is                                                  *
10
 *                                                                             *
11
 *         autotune time accuracy                                              *
12
 *                                                                             *
13
 *   "time" is the target time to optimize for.  Longer time limits require    *
14
 *   somewhat different tuning values, so this should be set to the typical    *
15
 *   time per move.  The default is 30 seconds per move if not specified.      *
16
 *                                                                             *
17
 *   "accuracy" is normally set to 4.  Since SMP search results and times are  *
18
 *   non-deterministic, running tests 1 time can be inaccurate.  This value is *
19
 *   used to determine how many times to run each test.  If you set it to two, *
20
 *   the entire test will take 1/2 as long.  Bigger numbers are better, but    *
21
 *   it is easy to make the test run for hours if you go too far.  A big value *
22
 *   will work best if allowed to run overnight.  Crafty will display a time   *
23
 *   estimate after determining the optimal benchmark settings.  If this time  *
24
 *   is excessive, a ^C will let you re-start Crafty and pick a more           *
25
 *   reasonable time/accuracy setting.                                         *
26
 *                                                                             *
27
 *   AutoTune() will tune the primary SMP controls, namely the values set by   *
28
 *   the commands smpgroup, smpmin, smpsd and smppsl.  It will NEVER change    *
29
 *   smpmt (max threads), smproot (split at root) and smpaffinity.  those are  *
30
 *   user choices and in general the default is optimal.  In general the       *
31
 *   values have min and max settings defined in data.c (search for autotune), *
32
 *   and this code will try multiple values in the given range to find an      *
33
 *   optimal setting.  For some of the values, it will test each value in the  *
34
 *   interval, but for values with a large range it will try reasonable        *
35
 *   (again, see data.c and the "tune" array) intervals.  If desired, the      *
36
 *   low/high limits can be changed along with the interval between samples,   *
37
 *   by modifying the autotune data in data.c.                                 *
38
 *                                                                             *
39
 *   Note that this command is best used before you go to eat or something as  *
40
 *   it will run a while.  If you ramp up the accuracy setting, it will take   *
41
 *   multiples of accuracy times longer.  Best results are likely obtained     *
42
 *   with a larger accuracy setting, but it needs to run overnight.            *
43
 *                                                                             *
44
 *******************************************************************************
45
 */
46
void AutoTune(int nargs, char *args[]) {
47
  unsigned int target_time = 3000, accuracy = 4, atstart, atend;
48
  unsigned int time, current, setting[64], times[64], last_time, stageii;
49
  int benchd, i, v, p, best, bestv, samples;
50
  FILE *craftyrc = fopen(".craftyrc", "a");
51
 
52
/*
53
 ************************************************************
54
 *                                                          *
55
 *  Initialize.                                             *
56
 *                                                          *
57
 ************************************************************
58
 */
59
  if (smp_max_threads < 2) {
60
    Print(4095, "ERROR: smpmt must be set to > 1 for tuning to work\n");
61
    return;
62
  }
63
  if (nargs > 1)
64
    target_time = atoi(args[1]) * 100;
65
  if (nargs > 2)
66
    accuracy = atoi(args[2]);
67
  Print(4095, "AutoTune()  time=%s  accuracy=%d\n",
68
      DisplayHHMMSS(target_time), accuracy);
69
/*
70
 ************************************************************
71
 *                                                          *
72
 *  First task is to find the benchmark setting that will   *
73
 *  run in the alotted time.  The Bench() command runs six  *
74
 *  positions, so we want the command to run in no more     *
75
 *  than six times the autotune time limit to average the   *
76
 *  specified time per move.  We break out of the loop when *
77
 *  bench takes more than 6x this time limit and use the    *
78
 *  previous value which just fit inside the limit.         *
79
 *                                                          *
80
 ************************************************************
81
 */
82
  atstart = ReadClock();
83
  stageii = 0;
84
  for (v = 0; v < autotune_params; v++)
85
    for (current = tune[v].min; current <= tune[v].max;
86
        current += tune[v].increment)
87
      stageii++;
88
  Print(4095, "Calculating optimal benchmark setting.\n");
89
  Print(4095, "Target time average = %s.\n", DisplayHHMMSS(6 * target_time));
90
  Print(4095, "Estimated run time (stage I) is %s.\n",
91
      DisplayHHMMSS(accuracy * 12 * target_time));
92
  Print(4095, "Estimated run time (stage II) is %s.\n",
93
      DisplayHHMMSS(accuracy * stageii * 4 * target_time));
94
  Print(4095, "\nBegin stage I (calibration)\n");
95
  last_time = 0;
96
  for (benchd = -5; benchd < 10; benchd++) {
97
    Print(4095, "bench %2d:", benchd);
98
    time = 0;
99
    for (v = 0; v < (int) accuracy; v++) // Pierre-Marie Baty -- added type cast
100
      time += Bench(benchd, 1);
101
    time /= accuracy;
102
    Print(4095, " ->%s\n", DisplayHHMMSS(time));
103
    if (time > 6 * target_time)
104
      break;
105
    last_time = time;
106
  }
107
  benchd--;
108
  Print(4095, "Optimal setting is " "bench %d" "\n", benchd);
109
  atend = ReadClock();
110
  Print(4095, "Actual runtime for Stage I: %s\n",
111
      DisplayHHMMSS(atend - atstart));
112
  Print(4095, "New estimated run time (stage II) is %s.\n",
113
      DisplayHHMMSS(accuracy * stageii * last_time));
114
  Print(4095, "\nBegin stage II (SMP testing).\n");
115
  atstart = ReadClock();
116
/*
117
 ************************************************************
118
 *                                                          *
119
 *  Next we simply take each option, one by one, and try    *
120
 *  reasonable values between the min/max values as defined *
121
 *  in data.c.                                              *
122
 *                                                          *
123
 *  The process is fairly simple, but very time-consuming.  *
124
 *  We will start at the min value for a single paramenter, *
125
 *  and run bench "accuracy" times and compute the average  *
126
 *  of the times.  We then repeat for the next step in the  *
127
 *  parameter, and continue until we try the max value that *
128
 *  is allowed.  We choose the parameter value that used    *
129
 *  the least amount of time which optimizes this value for *
130
 *  minimum time-to-depth.                                  *
131
 *                                                          *
132
 ************************************************************
133
 */
134
  for (v = 0; v < autotune_params; v++) {
135
    Print(4095, "auto-tuning %s (%d ~ %d by %d)\n", tune[v].description,
136
        tune[v].min, tune[v].max, tune[v].increment);
137
    current = *tune[v].parameter;
138
    samples = 0;
139
    if (v == 0 && tune[v].min > smp_max_threads) {
140
      samples = 1;
141
      times[0] = 0;
142
      setting[0] = smp_max_threads;
143
    } else
144
      for (current = tune[v].min; current <= tune[v].max;
145
          current += tune[v].increment) {
146
        Print(4095, "Testing %d: ", current);
147
        *tune[v].parameter = current;
148
        time = 0;
149
        for (p = 0; p < (int) accuracy; p++) // Pierre-Marie Baty -- added type cast
150
          time += Bench(benchd, 1);
151
        time /= accuracy;
152
        times[samples] = time;
153
        setting[samples++] = current;
154
        Print(4095, " ->%s\n", DisplayHHMMSS(time));
155
      }
156
    best = 0;
157
    bestv = times[0];
158
    for (i = 1; i < samples; i++)
159
      if (bestv > (int) times[i]) { // Pierre-Marie Baty -- added type cast
160
        bestv = times[i];
161
        best = i;
162
      }
163
    fprintf(craftyrc, "%s=%d\n", tune[v].command, setting[best]);
164
    Print(4095, "adding " "%s=%d" " to .craftyrc file.\n", tune[v].command,
165
        setting[best]);
166
  }
167
  atend = ReadClock();
168
  Print(4095, "Runtime for StageII: %s\n", DisplayHHMMSS(atend - atstart));
169
  fclose(craftyrc);
170
}