Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
official-stockfish
GitHub Repository: official-stockfish/stockfish
Path: blob/master/src/thread.h
506 views
1
/*
2
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3
Copyright (C) 2004-2026 The Stockfish developers (see AUTHORS file)
4
5
Stockfish is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9
10
Stockfish is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#ifndef THREAD_H_INCLUDED
20
#define THREAD_H_INCLUDED
21
22
#include <atomic>
23
#include <condition_variable>
24
#include <cstddef>
25
#include <cstdint>
26
#include <functional>
27
#include <memory>
28
#include <mutex>
29
#include <vector>
30
31
#include "memory.h"
32
#include "numa.h"
33
#include "position.h"
34
#include "search.h"
35
#include "thread_win32_osx.h"
36
37
namespace Stockfish {
38
39
40
class OptionsMap;
41
using Value = int;
42
43
// Sometimes we don't want to actually bind the threads, but the recipient still
44
// needs to think it runs on *some* NUMA node, such that it can access structures
45
// that rely on NUMA node knowledge. This class encapsulates this optional process
46
// such that the recipient does not need to know whether the binding happened or not.
47
class OptionalThreadToNumaNodeBinder {
48
public:
49
OptionalThreadToNumaNodeBinder(NumaIndex n) :
50
numaConfig(nullptr),
51
numaId(n) {}
52
53
OptionalThreadToNumaNodeBinder(const NumaConfig& cfg, NumaIndex n) :
54
numaConfig(&cfg),
55
numaId(n) {}
56
57
NumaReplicatedAccessToken operator()() const {
58
if (numaConfig != nullptr)
59
return numaConfig->bind_current_thread_to_numa_node(numaId);
60
else
61
return NumaReplicatedAccessToken(numaId);
62
}
63
64
private:
65
const NumaConfig* numaConfig;
66
NumaIndex numaId;
67
};
68
69
// Abstraction of a thread. It contains a pointer to the worker and a native thread.
70
// After construction, the native thread is started with idle_loop()
71
// waiting for a signal to start searching.
72
// When the signal is received, the thread starts searching and when
73
// the search is finished, it goes back to idle_loop() waiting for a new signal.
74
class Thread {
75
public:
76
Thread(Search::SharedState&,
77
std::unique_ptr<Search::ISearchManager>,
78
size_t,
79
size_t,
80
size_t,
81
OptionalThreadToNumaNodeBinder);
82
virtual ~Thread();
83
84
void idle_loop();
85
void start_searching();
86
void clear_worker();
87
void run_custom_job(std::function<void()> f);
88
89
void ensure_network_replicated();
90
91
// Thread has been slightly altered to allow running custom jobs, so
92
// this name is no longer correct. However, this class (and ThreadPool)
93
// require further work to make them properly generic while maintaining
94
// appropriate specificity regarding search, from the point of view of an
95
// outside user, so renaming of this function is left for whenever that happens.
96
void wait_for_search_finished();
97
size_t id() const { return idx; }
98
99
LargePagePtr<Search::Worker> worker;
100
std::function<void()> jobFunc;
101
102
private:
103
std::mutex mutex;
104
std::condition_variable cv;
105
size_t idx, idxInNuma, totalNuma, nthreads;
106
bool exit = false, searching = true; // Set before starting std::thread
107
NativeThread stdThread;
108
NumaReplicatedAccessToken numaAccessToken;
109
};
110
111
112
// ThreadPool struct handles all the threads-related stuff like init, starting,
113
// parking and, most importantly, launching a thread. All the access to threads
114
// is done through this class.
115
class ThreadPool {
116
public:
117
ThreadPool() {}
118
119
~ThreadPool() {
120
// destroy any existing thread(s)
121
if (threads.size() > 0)
122
{
123
main_thread()->wait_for_search_finished();
124
125
threads.clear();
126
}
127
}
128
129
ThreadPool(const ThreadPool&) = delete;
130
ThreadPool(ThreadPool&&) = delete;
131
132
ThreadPool& operator=(const ThreadPool&) = delete;
133
ThreadPool& operator=(ThreadPool&&) = delete;
134
135
void start_thinking(const OptionsMap&, Position&, StateListPtr&, Search::LimitsType);
136
void run_on_thread(size_t threadId, std::function<void()> f);
137
void wait_on_thread(size_t threadId);
138
size_t num_threads() const;
139
void clear();
140
void set(const NumaConfig& numaConfig,
141
Search::SharedState,
142
const Search::SearchManager::UpdateContext&);
143
144
Search::SearchManager* main_manager();
145
Thread* main_thread() const { return threads.front().get(); }
146
uint64_t nodes_searched() const;
147
uint64_t tb_hits() const;
148
Thread* get_best_thread() const;
149
void start_searching();
150
void wait_for_search_finished() const;
151
152
std::vector<size_t> get_bound_thread_count_by_numa_node() const;
153
154
void ensure_network_replicated();
155
156
std::atomic_bool stop, abortedSearch, increaseDepth;
157
158
auto cbegin() const noexcept { return threads.cbegin(); }
159
auto begin() noexcept { return threads.begin(); }
160
auto end() noexcept { return threads.end(); }
161
auto cend() const noexcept { return threads.cend(); }
162
auto size() const noexcept { return threads.size(); }
163
auto empty() const noexcept { return threads.empty(); }
164
165
private:
166
StateListPtr setupStates;
167
std::vector<std::unique_ptr<Thread>> threads;
168
std::vector<NumaIndex> boundThreadToNumaNode;
169
170
uint64_t accumulate(std::atomic<uint64_t> Search::Worker::* member) const {
171
172
uint64_t sum = 0;
173
for (auto&& th : threads)
174
sum += (th->worker.get()->*member).load(std::memory_order_relaxed);
175
return sum;
176
}
177
};
178
179
} // namespace Stockfish
180
181
#endif // #ifndef THREAD_H_INCLUDED
182
183