Rev 154 | Details | Compare with Previous | 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; |
||
| 156 | pmbaty | 49 | int benchd, i, v; unsigned int p; int best; unsigned int bestv; int samples; // Pierre-Marie Baty -- fixed types |
| 108 | pmbaty | 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"); |
||
| 154 | pmbaty | 61 | fclose(craftyrc); |
| 108 | pmbaty | 62 | return; |
| 63 | } |
||
| 64 | if (nargs > 1) |
||
| 65 | target_time = atoi(args[1]) * 100; |
||
| 66 | if (nargs > 2) |
||
| 67 | accuracy = atoi(args[2]); |
||
| 68 | Print(4095, "AutoTune() time=%s accuracy=%d\n", |
||
| 69 | DisplayHHMMSS(target_time), accuracy); |
||
| 70 | /* |
||
| 71 | ************************************************************ |
||
| 72 | * * |
||
| 73 | * First task is to find the benchmark setting that will * |
||
| 74 | * run in the alotted time. The Bench() command runs six * |
||
| 75 | * positions, so we want the command to run in no more * |
||
| 76 | * than six times the autotune time limit to average the * |
||
| 77 | * specified time per move. We break out of the loop when * |
||
| 78 | * bench takes more than 6x this time limit and use the * |
||
| 79 | * previous value which just fit inside the limit. * |
||
| 80 | * * |
||
| 81 | ************************************************************ |
||
| 82 | */ |
||
| 83 | atstart = ReadClock(); |
||
| 84 | stageii = 0; |
||
| 85 | for (v = 0; v < autotune_params; v++) |
||
| 86 | for (current = tune[v].min; current <= tune[v].max; |
||
| 87 | current += tune[v].increment) |
||
| 88 | stageii++; |
||
| 89 | Print(4095, "Calculating optimal benchmark setting.\n"); |
||
| 90 | Print(4095, "Target time average = %s.\n", DisplayHHMMSS(6 * target_time)); |
||
| 91 | Print(4095, "Estimated run time (stage I) is %s.\n", |
||
| 92 | DisplayHHMMSS(accuracy * 12 * target_time)); |
||
| 93 | Print(4095, "Estimated run time (stage II) is %s.\n", |
||
| 94 | DisplayHHMMSS(accuracy * stageii * 4 * target_time)); |
||
| 95 | Print(4095, "\nBegin stage I (calibration)\n"); |
||
| 96 | last_time = 0; |
||
| 97 | for (benchd = -5; benchd < 10; benchd++) { |
||
| 98 | Print(4095, "bench %2d:", benchd); |
||
| 99 | time = 0; |
||
| 156 | pmbaty | 100 | for (v = 0; v < (int) accuracy; v++) // Pierre-Marie Baty -- added type cast |
| 108 | pmbaty | 101 | time += Bench(benchd, 1); |
| 102 | time /= accuracy; |
||
| 103 | Print(4095, " ->%s\n", DisplayHHMMSS(time)); |
||
| 104 | if (time > 6 * target_time) |
||
| 105 | break; |
||
| 106 | last_time = time; |
||
| 107 | } |
||
| 108 | benchd--; |
||
| 109 | Print(4095, "Optimal setting is " "bench %d" "\n", benchd); |
||
| 110 | atend = ReadClock(); |
||
| 111 | Print(4095, "Actual runtime for Stage I: %s\n", |
||
| 112 | DisplayHHMMSS(atend - atstart)); |
||
| 113 | Print(4095, "New estimated run time (stage II) is %s.\n", |
||
| 114 | DisplayHHMMSS(accuracy * stageii * last_time)); |
||
| 115 | Print(4095, "\nBegin stage II (SMP testing).\n"); |
||
| 116 | atstart = ReadClock(); |
||
| 117 | /* |
||
| 118 | ************************************************************ |
||
| 119 | * * |
||
| 120 | * Next we simply take each option, one by one, and try * |
||
| 121 | * reasonable values between the min/max values as defined * |
||
| 122 | * in data.c. * |
||
| 123 | * * |
||
| 124 | * The process is fairly simple, but very time-consuming. * |
||
| 125 | * We will start at the min value for a single paramenter, * |
||
| 126 | * and run bench "accuracy" times and compute the average * |
||
| 127 | * of the times. We then repeat for the next step in the * |
||
| 128 | * parameter, and continue until we try the max value that * |
||
| 129 | * is allowed. We choose the parameter value that used * |
||
| 130 | * the least amount of time which optimizes this value for * |
||
| 131 | * minimum time-to-depth. * |
||
| 132 | * * |
||
| 133 | ************************************************************ |
||
| 134 | */ |
||
| 135 | for (v = 0; v < autotune_params; v++) { |
||
| 136 | Print(4095, "auto-tuning %s (%d ~ %d by %d)\n", tune[v].description, |
||
| 137 | tune[v].min, tune[v].max, tune[v].increment); |
||
| 138 | current = *tune[v].parameter; |
||
| 139 | samples = 0; |
||
| 156 | pmbaty | 140 | if (v == 0 && tune[v].min > (unsigned int) smp_max_threads) { // Pierre-Marie Baty -- added type cast |
| 108 | pmbaty | 141 | samples = 1; |
| 142 | times[0] = 0; |
||
| 143 | setting[0] = smp_max_threads; |
||
| 144 | } else |
||
| 145 | for (current = tune[v].min; current <= tune[v].max; |
||
| 146 | current += tune[v].increment) { |
||
| 147 | Print(4095, "Testing %d: ", current); |
||
| 148 | *tune[v].parameter = current; |
||
| 149 | time = 0; |
||
| 154 | pmbaty | 150 | for (p = 0; p < accuracy; p++) |
| 108 | pmbaty | 151 | time += Bench(benchd, 1); |
| 152 | time /= accuracy; |
||
| 153 | times[samples] = time; |
||
| 154 | setting[samples++] = current; |
||
| 155 | Print(4095, " ->%s\n", DisplayHHMMSS(time)); |
||
| 156 | } |
||
| 157 | best = 0; |
||
| 158 | bestv = times[0]; |
||
| 159 | for (i = 1; i < samples; i++) |
||
| 154 | pmbaty | 160 | if (bestv > times[i]) { |
| 108 | pmbaty | 161 | bestv = times[i]; |
| 162 | best = i; |
||
| 163 | } |
||
| 164 | fprintf(craftyrc, "%s=%d\n", tune[v].command, setting[best]); |
||
| 165 | Print(4095, "adding " "%s=%d" " to .craftyrc file.\n", tune[v].command, |
||
| 166 | setting[best]); |
||
| 167 | } |
||
| 168 | atend = ReadClock(); |
||
| 169 | Print(4095, "Runtime for StageII: %s\n", DisplayHHMMSS(atend - atstart)); |
||
| 170 | fclose(craftyrc); |
||
| 171 | } |