mirror of
https://github.com/sockspls/badfish
synced 2025-07-11 19:49:14 +00:00
Don't allocate MAX_THREADS hash tables if not necessary
This prevent crashing on mobile devices with limited RAM, currently with MAX_THREADS = 32 we would need 44MB that could be too much for a poor cellphone. No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
fecefbb99c
commit
339e1b49f6
5 changed files with 40 additions and 19 deletions
|
@ -85,7 +85,7 @@ namespace {
|
||||||
|
|
||||||
/// MaterialInfoTable c'tor and d'tor allocate and free the space for Endgames
|
/// MaterialInfoTable c'tor and d'tor allocate and free the space for Endgames
|
||||||
|
|
||||||
void MaterialInfoTable::init() { Base::init(); funcs = new Endgames(); }
|
void MaterialInfoTable::init() { Base::init(); if (!funcs) funcs = new Endgames(); }
|
||||||
MaterialInfoTable::~MaterialInfoTable() { delete funcs; }
|
MaterialInfoTable::~MaterialInfoTable() { delete funcs; }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -435,15 +435,18 @@ bool think(Position& pos, const SearchLimits& limits, Move searchMoves[]) {
|
||||||
UCIMultiPV = Options["MultiPV"].value<int>();
|
UCIMultiPV = Options["MultiPV"].value<int>();
|
||||||
SkillLevel = Options["Skill level"].value<int>();
|
SkillLevel = Options["Skill level"].value<int>();
|
||||||
|
|
||||||
ThreadsMgr.read_uci_options();
|
|
||||||
read_evaluation_uci_options(pos.side_to_move());
|
read_evaluation_uci_options(pos.side_to_move());
|
||||||
|
ThreadsMgr.read_uci_options();
|
||||||
|
|
||||||
|
// If needed allocate pawn and material hash tables and adjust TT size
|
||||||
|
ThreadsMgr.init_hash_tables();
|
||||||
|
TT.set_size(Options["Hash"].value<int>());
|
||||||
|
|
||||||
if (Options["Clear Hash"].value<bool>())
|
if (Options["Clear Hash"].value<bool>())
|
||||||
{
|
{
|
||||||
Options["Clear Hash"].set_value("false");
|
Options["Clear Hash"].set_value("false");
|
||||||
TT.clear();
|
TT.clear();
|
||||||
}
|
}
|
||||||
TT.set_size(Options["Hash"].value<int>());
|
|
||||||
|
|
||||||
// Do we have to play with skill handicap? In this case enable MultiPV that
|
// Do we have to play with skill handicap? In this case enable MultiPV that
|
||||||
// we will use behind the scenes to retrieve a set of possible moves.
|
// we will use behind the scenes to retrieve a set of possible moves.
|
||||||
|
|
|
@ -64,50 +64,48 @@ void ThreadsManager::read_uci_options() {
|
||||||
activeThreads = Options["Threads"].value<int>();
|
activeThreads = Options["Threads"].value<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// init_threads() is called during startup. Initializes locks and condition
|
// init_threads() is called during startup. Initializes locks and condition
|
||||||
// variables and launches all threads sending them immediately to sleep.
|
// variables and launches all threads sending them immediately to sleep.
|
||||||
|
|
||||||
void ThreadsManager::init_threads() {
|
void ThreadsManager::init_threads() {
|
||||||
|
|
||||||
int i, arg[MAX_THREADS];
|
int arg[MAX_THREADS];
|
||||||
bool ok;
|
|
||||||
|
|
||||||
// This flag is needed to properly end the threads when program exits
|
// This flag is needed to properly end the threads when program exits
|
||||||
allThreadsShouldExit = false;
|
allThreadsShouldExit = false;
|
||||||
|
|
||||||
// Threads will sent to sleep as soon as created, only main thread is kept alive
|
// Threads will sent to sleep as soon as created, only main thread is kept alive
|
||||||
activeThreads = 1;
|
activeThreads = 1;
|
||||||
|
threads[0].state = THREAD_SEARCHING;
|
||||||
|
|
||||||
|
// Allocate pawn and material hash tables for main thread
|
||||||
|
init_hash_tables();
|
||||||
|
|
||||||
lock_init(&mpLock);
|
lock_init(&mpLock);
|
||||||
|
|
||||||
for (i = 0; i < MAX_THREADS; i++)
|
|
||||||
{
|
|
||||||
// Initialize thread and split point locks
|
// Initialize thread and split point locks
|
||||||
|
for (int i = 0; i < MAX_THREADS; i++)
|
||||||
|
{
|
||||||
lock_init(&threads[i].sleepLock);
|
lock_init(&threads[i].sleepLock);
|
||||||
cond_init(&threads[i].sleepCond);
|
cond_init(&threads[i].sleepCond);
|
||||||
|
|
||||||
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
|
for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++)
|
||||||
lock_init(&(threads[i].splitPoints[j].lock));
|
lock_init(&(threads[i].splitPoints[j].lock));
|
||||||
|
|
||||||
// All threads but first should be set to THREAD_INITIALIZING
|
|
||||||
threads[i].state = (i == 0 ? THREAD_SEARCHING : THREAD_INITIALIZING);
|
|
||||||
|
|
||||||
// Not in Threads c'tor to avoid global initialization order issues
|
|
||||||
threads[i].pawnTable.init();
|
|
||||||
threads[i].materialTable.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and startup the threads
|
// Create and startup all the threads but the main that is already running
|
||||||
for (i = 1; i < MAX_THREADS; i++)
|
for (int i = 1; i < MAX_THREADS; i++)
|
||||||
{
|
{
|
||||||
|
threads[i].state = THREAD_INITIALIZING;
|
||||||
arg[i] = i;
|
arg[i] = i;
|
||||||
|
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
pthread_t pthread[1];
|
pthread_t pthread[1];
|
||||||
ok = (pthread_create(pthread, NULL, init_thread, (void*)(&arg[i])) == 0);
|
bool ok = (pthread_create(pthread, NULL, init_thread, (void*)(&arg[i])) == 0);
|
||||||
pthread_detach(pthread[0]);
|
pthread_detach(pthread[0]);
|
||||||
#else
|
#else
|
||||||
ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&arg[i]), 0, NULL) != NULL);
|
bool ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&arg[i]), 0, NULL) != NULL);
|
||||||
#endif
|
#endif
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
|
@ -150,6 +148,22 @@ void ThreadsManager::exit_threads() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// init_hash_tables() dynamically allocates pawn and material hash tables
|
||||||
|
// according to the number of active threads. This avoids preallocating
|
||||||
|
// memory for all possible threads if only few are used as, for instance,
|
||||||
|
// on mobile devices where memory is scarce and allocating for MAX_THREADS
|
||||||
|
// threads could even result in a crash.
|
||||||
|
|
||||||
|
void ThreadsManager::init_hash_tables() {
|
||||||
|
|
||||||
|
for (int i = 0; i < activeThreads; i++)
|
||||||
|
{
|
||||||
|
threads[i].pawnTable.init();
|
||||||
|
threads[i].materialTable.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// cutoff_at_splitpoint() checks whether a beta cutoff has occurred in
|
// cutoff_at_splitpoint() checks whether a beta cutoff has occurred in
|
||||||
// the thread's currently active split point, or in some ancestor of
|
// the thread's currently active split point, or in some ancestor of
|
||||||
// the current split point.
|
// the current split point.
|
||||||
|
|
|
@ -105,6 +105,7 @@ public:
|
||||||
Thread& operator[](int threadID) { return threads[threadID]; }
|
Thread& operator[](int threadID) { return threads[threadID]; }
|
||||||
void init_threads();
|
void init_threads();
|
||||||
void exit_threads();
|
void exit_threads();
|
||||||
|
void init_hash_tables();
|
||||||
|
|
||||||
int min_split_depth() const { return minimumSplitDepth; }
|
int min_split_depth() const { return minimumSplitDepth; }
|
||||||
int active_threads() const { return activeThreads; }
|
int active_threads() const { return activeThreads; }
|
||||||
|
|
5
src/tt.h
5
src/tt.h
|
@ -148,11 +148,14 @@ struct SimpleHash {
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
|
|
||||||
|
if (entries)
|
||||||
|
return;
|
||||||
|
|
||||||
entries = new (std::nothrow) Entry[HashSize];
|
entries = new (std::nothrow) Entry[HashSize];
|
||||||
if (!entries)
|
if (!entries)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to allocate " << HashSize * sizeof(Entry)
|
std::cerr << "Failed to allocate " << HashSize * sizeof(Entry)
|
||||||
<< " bytes for material hash table." << std::endl;
|
<< " bytes for hash table." << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
memset(entries, 0, HashSize * sizeof(Entry));
|
memset(entries, 0, HashSize * sizeof(Entry));
|
||||||
|
|
Loading…
Add table
Reference in a new issue