Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup and simplify NNUE code. #3441

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,49 @@ T* align_ptr_up(T* ptr)
return reinterpret_cast<T*>(reinterpret_cast<char*>((ptrint + (Alignment - 1)) / Alignment * Alignment));
}

template <typename T>
class ValueListInserter {
public:
ValueListInserter(T* v, std::size_t& s) :
values(v),
size(&s)
{
}

void push_back(const T& value) { values[(*size)++] = value; }
private:
T* values;
std::size_t* size;
};

template <typename T, std::size_t MaxSize>
class ValueList {

public:
std::size_t size() const { return size_; }
void resize(std::size_t newSize) { size_ = newSize; }
void push_back(const T& value) { values_[size_++] = value; }
T& operator[](std::size_t index) { return values_[index]; }
T* begin() { return values_; }
T* end() { return values_ + size_; }
const T& operator[](std::size_t index) const { return values_[index]; }
const T* begin() const { return values_; }
const T* end() const { return values_ + size_; }
operator ValueListInserter<T>() { return ValueListInserter(values_, size_); }

void swap(ValueList& other) {
const std::size_t maxSize = std::max(size_, other.size_);
for (std::size_t i = 0; i < maxSize; ++i) {
std::swap(values_[i], other.values_[i]);
}
std::swap(size_, other.size_);
}

private:
T values_[MaxSize];
std::size_t size_ = 0;
};

/// xorshift64star Pseudo-Random Number Generator
/// This class is based on original code written and dedicated
/// to the public domain by Sebastiano Vigna (2014).
Expand Down
54 changes: 0 additions & 54 deletions src/nnue/architectures/halfkp_256x2-32-32.h

This file was deleted.

69 changes: 0 additions & 69 deletions src/nnue/features/feature_set.h

This file was deleted.

45 changes: 0 additions & 45 deletions src/nnue/features/features_common.h

This file was deleted.

65 changes: 32 additions & 33 deletions src/nnue/features/half_kp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,69 +19,68 @@
//Definition of input features HalfKP of NNUE evaluation function

#include "half_kp.h"
#include "index_list.h"

#include "../../position.h"

namespace Stockfish::Eval::NNUE::Features {

// Orient a square according to perspective (rotates by 180 for black)
inline Square orient(Color perspective, Square s) {
inline Square HalfKP::orient(Color perspective, Square s) {
return Square(int(s) ^ (bool(perspective) * 63));
}

// Index of a feature for a given king position and another piece on some square
inline IndexType make_index(Color perspective, Square s, Piece pc, Square ksq) {
inline IndexType HalfKP::make_index(Color perspective, Square s, Piece pc, Square ksq) {
return IndexType(orient(perspective, s) + PieceSquareIndex[perspective][pc] + PS_NB * ksq);
}

// Get a list of indices for active features
template <Side AssociatedKing>
void HalfKP<AssociatedKing>::append_active_indices(
const Position& pos, Color perspective, IndexList* active) {

void HalfKP::append_active_indices(
const Position& pos,
Color perspective,
ValueListInserter<IndexType> active
) {
Square ksq = orient(perspective, pos.square<KING>(perspective));
Bitboard bb = pos.pieces() & ~pos.pieces(KING);
while (bb)
{
Square s = pop_lsb(bb);
active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
active.push_back(make_index(perspective, s, pos.piece_on(s), ksq));
}
}


// append_changed_indices() : get a list of indices for recently changed features

// IMPORTANT: The `pos` in this function is pretty much useless as it
// is not always the position the features are updated to. The feature
// transformer code right now can update multiple accumulators per move,
// but since Stockfish only keeps the full state of the current leaf
// search position it is not possible to always pass here the position for
// which the accumulator is being updated. Therefore the only thing that
// can be reliably extracted from `pos` is the king square for the king
// of the `perspective` color (note: not even the other king's square will
// match reality in all cases, this is also the reason why `dp` is passed
// as a parameter and not extracted from pos.state()). This is of particular
// problem for future nets with other feature sets, where updating the active
// feature might require more information from the intermediate positions. In
// this case the only easy solution is to remove the multiple updates from
// the feature transformer update code and only update the accumulator for
// the current leaf position (the position after the move).

template <Side AssociatedKing>
void HalfKP<AssociatedKing>::append_changed_indices(
const Position& pos, const DirtyPiece& dp, Color perspective,
IndexList* removed, IndexList* added) {

Square ksq = orient(perspective, pos.square<KING>(perspective));
void HalfKP::append_changed_indices(
Square ksq,
StateInfo* st,
Color perspective,
ValueListInserter<IndexType> removed,
ValueListInserter<IndexType> added
) {
const auto& dp = st->dirtyPiece;
Square oriented_ksq = orient(perspective, ksq);
for (int i = 0; i < dp.dirty_num; ++i) {
Piece pc = dp.piece[i];
if (type_of(pc) == KING) continue;
if (dp.from[i] != SQ_NONE)
removed->push_back(make_index(perspective, dp.from[i], pc, ksq));
removed.push_back(make_index(perspective, dp.from[i], pc, oriented_ksq));
if (dp.to[i] != SQ_NONE)
added->push_back(make_index(perspective, dp.to[i], pc, ksq));
added.push_back(make_index(perspective, dp.to[i], pc, oriented_ksq));
}
}

template class HalfKP<Side::Friend>;
int HalfKP::update_cost(StateInfo* st) {
return st->dirtyPiece.dirty_num;
}

int HalfKP::refresh_cost(const Position& pos) {
return pos.count<ALL_PIECES>() - 2;
}

bool HalfKP::requires_refresh(StateInfo* st, Color perspective) {
return st->dirtyPiece.piece[0] == make_piece(perspective, KING);
}

} // namespace Stockfish::Eval::NNUE::Features
Loading