-
-
-/// benchmark() runs a simple benchmark by letting Stockfish analyze a set
-/// of positions for a given limit each. There are five parameters; the
-/// transposition table size, the number of search threads that should
-/// be used, the limit value spent for each position (optional, default is
-/// depth 12), an optional file name where to look for positions in fen
-/// format (defaults are the positions defined above) and the type of the
-/// limit value: depth (default), time in secs or number of nodes.
-
-void benchmark(int argc, char* argv[]) {
-
- vector<string> fenList;
- Search::LimitsType limits;
- int64_t totalNodes;
- int time;
-
- // Assign default values to missing arguments
- string ttSize = argc > 2 ? argv[2] : "128";
- string threads = argc > 3 ? argv[3] : "1";
- string valStr = argc > 4 ? argv[4] : "12";
- string fenFile = argc > 5 ? argv[5] : "default";
- string valType = argc > 6 ? argv[6] : "depth";
-
- Options["Hash"].set_value(ttSize);
- Options["Threads"].set_value(threads);
- Options["OwnBook"].set_value("false");
-
- // Search should be limited by nodes, time or depth ?
- if (valType == "nodes")
- limits.maxNodes = atoi(valStr.c_str());
- else if (valType == "time")
- limits.maxTime = 1000 * atoi(valStr.c_str()); // maxTime is in ms
- else
- limits.maxDepth = atoi(valStr.c_str());
-
- // Do we need to load positions from a given FEN file?
- if (fenFile == "default")
- for (int i = 0; *Defaults[i]; i++)
- fenList.push_back(Defaults[i]);
- else
- {
- string fen;
- ifstream f(fenFile.c_str());
-
- if (!f.is_open())
- {
- cerr << "Unable to open file " << fenFile << endl;
- exit(EXIT_FAILURE);
- }
-
- while (getline(f, fen))
- if (!fen.empty())
- fenList.push_back(fen);
-
- f.close();
- }
-
- // Ok, let's start the benchmark !
- totalNodes = 0;
- time = get_system_time();
-
- for (size_t i = 0; i < fenList.size(); i++)
- {
- Position pos(fenList[i], false, 0);
-
- cerr << "\nBench position: " << i + 1 << '/' << fenList.size() << endl;
-
- if (valType == "perft")
- {
- int64_t cnt = Search::perft(pos, limits.maxDepth * ONE_PLY);
-
- cerr << "\nPerft " << limits.maxDepth
- << " nodes counted: " << cnt << endl;
-
- totalNodes += cnt;
- }
- else
- {
- Threads.start_thinking(pos, limits, vector<Move>(), false);
- totalNodes += Search::RootPosition.nodes_searched();
- }
- }
-
- time = get_system_time() - time;
-
- cerr << "\n==============================="
- << "\nTotal time (ms) : " << time
- << "\nNodes searched : " << totalNodes
- << "\nNodes/second : " << (int)(totalNodes / (time / 1000.0)) << endl;
+// clang-format on
+
+} // namespace
+
+namespace Stockfish {
+
+// Builds a list of UCI commands to be run by bench. There
+// are five parameters: TT size in MB, number of search threads that
+// should be used, the limit value spent for each position, a file name
+// where to look for positions in FEN format, and the type of the limit:
+// depth, perft, nodes and movetime (in milliseconds). Examples:
+//
+// bench : search default positions up to depth 13
+// bench 64 1 15 : search default positions up to depth 15 (TT = 64MB)
+// bench 64 1 100000 default nodes : search default positions for 100K nodes each
+// bench 64 4 5000 current movetime : search current position with 4 threads for 5 sec
+// bench 16 1 5 blah perft : run a perft 5 on positions in file "blah"
+std::vector<std::string> setup_bench(const Position& current, std::istream& is) {
+
+ std::vector<std::string> fens, list;
+ std::string go, token;
+
+ // Assign default values to missing arguments
+ std::string ttSize = (is >> token) ? token : "16";
+ std::string threads = (is >> token) ? token : "1";
+ std::string limit = (is >> token) ? token : "13";
+ std::string fenFile = (is >> token) ? token : "default";
+ std::string limitType = (is >> token) ? token : "depth";
+
+ go = limitType == "eval" ? "eval" : "go " + limitType + " " + limit;
+
+ if (fenFile == "default")
+ fens = Defaults;
+
+ else if (fenFile == "current")
+ fens.push_back(current.fen());
+
+ else
+ {
+ std::string fen;
+ std::ifstream file(fenFile);
+
+ if (!file.is_open())
+ {
+ std::cerr << "Unable to open file " << fenFile << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ while (getline(file, fen))
+ if (!fen.empty())
+ fens.push_back(fen);
+
+ file.close();
+ }
+
+ list.emplace_back("setoption name Threads value " + threads);
+ list.emplace_back("setoption name Hash value " + ttSize);
+ list.emplace_back("ucinewgame");
+
+ for (const std::string& fen : fens)
+ if (fen.find("setoption") != std::string::npos)
+ list.emplace_back(fen);
+ else
+ {
+ list.emplace_back("position fen " + fen);
+ list.emplace_back(go);
+ }
+
+ return list;