mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-23 05:07:14 +00:00
Speedup movegen with VBMI2
Passed STC LLR: 2.96 (-2.94,2.94) <0.00,2.00> Total: 166720 W: 43191 L: 42701 D: 80828 Ptnml(0-2): 348, 18567, 45069, 18999, 377 https://tests.stockfishchess.org/tests/view/686ae98dfe0f2fe354c0c867 Refactor movegen to emit to a vector with 16-bit elements, which enables a speedup with AVX512-VBMI2 when writing moves to the move list. Very crude timing measurements of perft via timing ./stockfish "go perft 7" demonstrates approximately 17% perft speedup: Summary ./Stockfish-dev/src/stockfish 'go perft 7' ran 1.17 ± 0.04 times faster than ./Stockfish-base/src/stockfish 'go perft 7' Estimated overall nps increase of 0.4% via speedtest: 33605229 -> 33749825 (many thanks JonathanHallstrom). The corresponding arch is avx512icl as it is a good baseline for consumer avx-512 feature set support; Intel Ice Lake was the first consumer AVX-512 CPU and it is a decent subset of what AMD Zen 4 supports. closes https://github.com/official-stockfish/Stockfish/pull/6153 No functional change
This commit is contained in:
+20
-10
@@ -123,7 +123,7 @@ MovePicker::MovePicker(const Position& p, Move ttm, int th, const CapturePieceTo
|
||||
// Captures are ordered by Most Valuable Victim (MVV), preferring captures
|
||||
// with a good history. Quiets moves are ordered using the history tables.
|
||||
template<GenType Type>
|
||||
void MovePicker::score() {
|
||||
ExtMove* MovePicker::score(MoveList<Type>& ml) {
|
||||
|
||||
static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
|
||||
|
||||
@@ -138,8 +138,12 @@ void MovePicker::score() {
|
||||
threatByLesser[QUEEN] = pos.attacks_by<ROOK>(~us) | threatByLesser[ROOK];
|
||||
}
|
||||
|
||||
for (auto& m : *this)
|
||||
ExtMove* it = cur;
|
||||
for (auto move : ml)
|
||||
{
|
||||
ExtMove& m = *it++;
|
||||
m = move;
|
||||
|
||||
const Square from = m.from_sq();
|
||||
const Square to = m.to_sq();
|
||||
const Piece pc = pos.moved_piece(m);
|
||||
@@ -189,6 +193,7 @@ void MovePicker::score() {
|
||||
}
|
||||
}
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
// Returns the next move satisfying a predicate function.
|
||||
@@ -222,14 +227,16 @@ top:
|
||||
|
||||
case CAPTURE_INIT :
|
||||
case PROBCUT_INIT :
|
||||
case QCAPTURE_INIT :
|
||||
case QCAPTURE_INIT : {
|
||||
MoveList<CAPTURES> ml(pos);
|
||||
|
||||
cur = endBadCaptures = moves;
|
||||
endCur = endCaptures = generate<CAPTURES>(pos, cur);
|
||||
endCur = endCaptures = score<CAPTURES>(ml);
|
||||
|
||||
score<CAPTURES>();
|
||||
partial_insertion_sort(cur, endCur, std::numeric_limits<int>::min());
|
||||
++stage;
|
||||
goto top;
|
||||
}
|
||||
|
||||
case GOOD_CAPTURE :
|
||||
if (select([&]() {
|
||||
@@ -246,9 +253,10 @@ top:
|
||||
case QUIET_INIT :
|
||||
if (!skipQuiets)
|
||||
{
|
||||
endCur = endGenerated = generate<QUIETS>(pos, cur);
|
||||
MoveList<QUIETS> ml(pos);
|
||||
|
||||
endCur = endGenerated = score<QUIETS>(ml);
|
||||
|
||||
score<QUIETS>();
|
||||
partial_insertion_sort(cur, endCur, -3560 * depth);
|
||||
}
|
||||
|
||||
@@ -283,14 +291,16 @@ top:
|
||||
|
||||
return Move::none();
|
||||
|
||||
case EVASION_INIT :
|
||||
case EVASION_INIT : {
|
||||
MoveList<EVASIONS> ml(pos);
|
||||
|
||||
cur = moves;
|
||||
endCur = endGenerated = generate<EVASIONS>(pos, cur);
|
||||
endCur = endGenerated = score<EVASIONS>(ml);
|
||||
|
||||
score<EVASIONS>();
|
||||
partial_insertion_sort(cur, endCur, std::numeric_limits<int>::min());
|
||||
++stage;
|
||||
[[fallthrough]];
|
||||
}
|
||||
|
||||
case EVASION :
|
||||
case QCAPTURE :
|
||||
|
||||
Reference in New Issue
Block a user