1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-01 17:19:36 +00:00

[cluster] Fix oversight in TT key reuse

In the original code, the position key stored in the TT is used to probe&store TT entries after message passing. Since we only store part of the bits in the TT, this leads to incorrect rehashing. This is fixed in this patch storing also the full key in the send buffers, and using that for hashing after message arrival.

Short testing with 4 ranks (old vs new) shows this is effective:
Score of mpiold vs mpinew: 84 - 275 - 265  [0.347] 624
Elo difference: -109.87 +/- 20.88
This commit is contained in:
Joost VandeVondele 2018-12-04 21:59:07 +01:00 committed by Stéphane Nicolet
parent 2659c407c4
commit 2559c20c6e
4 changed files with 26 additions and 22 deletions

View file

@ -357,7 +357,7 @@ ifeq ($(OS), Android)
endif
### 3.10 MPI
ifeq ($(CXX),$(filter $(CXX),mpicxx mpic++ mpiCC))
ifeq ($(CXX),$(filter $(CXX),mpicxx mpic++ mpiCC mpicxx.mpich))
mpi = yes
endif

View file

@ -46,7 +46,7 @@ static MPI_Comm MoveComm = MPI_COMM_NULL;
static MPI_Comm StopComm = MPI_COMM_NULL;
static MPI_Datatype TTEntryDatatype = MPI_DATATYPE_NULL;
static std::vector<TTEntry> TTBuff;
static std::vector<KeyedTTEntry> TTBuff;
static MPI_Op BestMoveOp = MPI_OP_NULL;
static MPI_Datatype MIDatatype = MPI_DATATYPE_NULL;
@ -65,14 +65,16 @@ static void BestMove(void* in, void* inout, int* len, MPI_Datatype* datatype) {
void init() {
int thread_support;
constexpr std::array<int, 6> TTblocklens = {1, 1, 1, 1, 1, 1};
const std::array<MPI_Aint, 6> TTdisps = {offsetof(TTEntry, key16),
offsetof(TTEntry, move16),
offsetof(TTEntry, value16),
offsetof(TTEntry, eval16),
offsetof(TTEntry, genBound8),
offsetof(TTEntry, depth8)};
const std::array<MPI_Datatype, 6> TTtypes = {MPI_UINT16_T,
constexpr std::array<int, 7> TTblocklens = {1, 1, 1, 1, 1, 1, 1};
const std::array<MPI_Aint, 7> TTdisps = {offsetof(KeyedTTEntry, first),
offsetof(KeyedTTEntry, second) + offsetof(TTEntry, key16),
offsetof(KeyedTTEntry, second) + offsetof(TTEntry, move16),
offsetof(KeyedTTEntry, second) + offsetof(TTEntry, value16),
offsetof(KeyedTTEntry, second) + offsetof(TTEntry, eval16),
offsetof(KeyedTTEntry, second) + offsetof(TTEntry, genBound8),
offsetof(KeyedTTEntry, second) + offsetof(TTEntry, depth8)};
const std::array<MPI_Datatype, 7> TTtypes = {MPI_UINT64_T,
MPI_UINT16_T,
MPI_UINT16_T,
MPI_INT16_T,
MPI_INT16_T,
@ -95,7 +97,7 @@ void init() {
TTBuff.resize(TTSendBufferSize * world_size);
MPI_Type_create_struct(6, TTblocklens.data(), TTdisps.data(), TTtypes.data(),
MPI_Type_create_struct(7, TTblocklens.data(), TTdisps.data(), TTtypes.data(),
&TTEntryDatatype);
MPI_Type_commit(&TTEntryDatatype);
@ -185,12 +187,13 @@ int rank() {
}
void save(Thread* thread, TTEntry* tte,
Key k, Value v, Bound b, Depth d, Move m, Value ev, uint8_t g) {
tte->save(k, v, b, d, m, ev, g);
Key k, Value v, Bound b, Depth d, Move m, Value ev) {
tte->save(k, v, b, d, m, ev);
// Try to add to thread's send buffer
{
std::lock_guard<Mutex> lk(thread->ttBuffer.mutex);
thread->ttBuffer.buffer.replace(*tte);
thread->ttBuffer.buffer.replace(KeyedTTEntry(k,*tte));
}
// Communicate on main search thread
@ -208,9 +211,9 @@ void save(Thread* thread, TTEntry* tte,
if (flag) {
// Save all recieved entries
for (auto&& e : TTBuff) {
replace_tte = TT.probe(e.key(), found);
replace_tte->save(e.key(), e.value(), e.bound(), e.depth(),
e.move(), e.eval(), e.gen());
replace_tte = TT.probe(e.first, found);
replace_tte->save(e.first, e.second.value(), e.second.bound(), e.second.depth(),
e.second.move(), e.second.eval());
}
// Reset send buffer

View file

@ -39,17 +39,19 @@ struct MoveInfo {
};
#ifdef USE_MPI
using KeyedTTEntry = std::pair<Key, TTEntry>;
constexpr std::size_t TTSendBufferSize = 16;
template <std::size_t N> class TTSendBuffer : public std::array<TTEntry, N> {
template <std::size_t N> class TTSendBuffer : public std::array<KeyedTTEntry, N> {
struct Compare {
inline bool operator()(const TTEntry& lhs, const TTEntry& rhs) {
return lhs.depth() > rhs.depth();
inline bool operator()(const KeyedTTEntry& lhs, const KeyedTTEntry& rhs) {
return lhs.second.depth() > rhs.second.depth();
}
};
Compare compare;
public:
bool replace(const TTEntry& value) {
bool replace(const KeyedTTEntry& value) {
if (compare(value, this->front())) {
std::pop_heap(this->begin(), this->end(), compare);
this->back() = value;

View file

@ -41,7 +41,6 @@ namespace Cluster {
struct TTEntry {
Key key() const { return (Key )(key16) << 48; }
Move move() const { return (Move )move16; }
Value value() const { return (Value)value16; }
Value eval() const { return (Value)eval16; }