-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Syntaxic sugar for Position::see_ge(move, threshold) #5529
base: master
Are you sure you want to change the base?
Conversation
clang-format 18 needs to be run on this PR. (execution 10300593128 / attempt 1) |
@@ -238,7 +238,7 @@ Move MovePicker::next_move(bool skipQuiets) { | |||
case GOOD_CAPTURE : | |||
if (select<Next>([&]() { | |||
// Move losing capture to endBadCaptures to be tried later | |||
return pos.see_ge(*cur, -cur->value / 18) ? true | |||
return pos.see(*cur) >= (-cur->value / 18) ? true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing PR!
Now one question I wanted to ask for so long, is that for such moves, can't we save the see value into the move struct such that we reuse it when we want to prune?, the code in search looks like redundant work to me, IIUC that should be a (nice) speedup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there is no function in master (nor in this PR) to calculate the SEE value of a move, we can only compare that value to a lower bound via see_ge()
I am convinced that this is important stuff concerning the readability and the ease of reasoning about Static Exchange Evaluation of moves, when we write or tweak our see()-related pruning algorithms in There was a furry of see() pruning tests ten years ago, and much less these days... In retrospect the introduction of pos.see_ge() in #822 , albeit nice in itself for the speed it has given, has slowed down the creativity of the team for new see() improvements, just because the syntax is more painful and we subconsciously refuse to work with it. Compare these two versions:
Honestly, are we able to tell without thinking what kind of comparison we do in the first version? Now, and also in six months when we come back to the code? It takes me about 5 seconds each time I read the code in master to get each line right, and 5 more seconds to double-check! |
Syntactic sugar around Position::see_ge(), so that we can use the more readable pos.see(move) >= threshold instead of pos.see_ge(move, threshold), and similar readable code for the other comparison operators. Closes official-stockfish/Stockfish#5529 No functional change.
@@ -1019,7 +1019,7 @@ Value Search::Worker::search( | |||
lmrDepth = std::max(lmrDepth, 0); | |||
|
|||
// Prune moves with negative SEE (~4 Elo) | |||
if (!pos.see_ge(move, -24 * lmrDepth * lmrDepth)) | |||
if (pos.see(move) < -24 * lmrDepth * lmrDepth) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there is no function in master (nor in this PR) to calculate the SEE value of a move, we can only compare that value to an upper bound or a lower bound via see_ge()
@snicolet I'm referring to here, aren't we calling the function again on the move, if we are passing move to the function aren't we calculating the result for such move in this position.. is this call not redundant to the ones in the movepicker?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we save the result S. and reuse it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not a function, this is just syntaxic sugar...
pos.see(move) < A
is strictly equivalent to
!pos.see_ge(move, A)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I see so it's like alpha-beta?
So you are saying that the value is not exact for some reason,
is it not possible to match bounds at least, just something like the saved bounds in TT, where we at least match windows/thresholds?
&& (ttData.bound & (ttData.value >= beta ? BOUND_LOWER : BOUND_UPPER)))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i.e. if a see_ge value fails high over +3000, is calculating see_ge of threshold -90000 relevant?
Syntactic sugar around Position::see_ge(), so that we can use the more readable pos.see(move) >= threshold instead of pos.see_ge(move, threshold), and similar readable code for the other comparison operators. Closes official-stockfish/Stockfish#5529 No functional change.
I think a non-reg STC would be good, because this has shown to be quite the slowdown for many engines Edit: sorry, I misread and missed the operator overloading Great stuff in this case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea imo, please use using
instead of typedef
to be consistent with the code
what i don't like is that there are now two ways of doing this and not one consistent one, i think it makes sense if the see_ge function is private and only useable over the see function, but then i also don't like that the return type of see() (the pair) is useable
something like this should cover both cases and prevent any misuse
https://godbolt.org/z/nve76Kh5x
I have tested speed locally with both clang and gcc, and found no speed penalty.
|
Syntactic sugar around Position::see_ge(), so that we can use the more readable pos.see(move) >= threshold instead of pos.see_ge(move, threshold), and similar readable code for the other comparison operators. Closes official-stockfish/Stockfish#5529 No functional change.
Syntactic sugar around Position::see_ge(), so that we can use the more readable pos.see(move) >= threshold instead of pos.see_ge(move, threshold), and similar readable code for the other comparison operators. Patch tested locally for speed with both clang and gcc, no speed penalty found. Non-regression test started here: https://tests.stockfishchess.org/tests/view/66b49f254ff211be9d4edf2a Closes official-stockfish#5529 No functional change.
Sorry about the noise I know this PR is only related to syntaxtic sugar but I was wondering about the bigger picture,
|
There is no guarantee where a good capture will beat the SEE threshold (and vice versa), though, because the way we determine good captures in movepicker is not a fixed value but relies on capture history |
Yes, so what you do is this to skip the work.......
|
ah, I see what you mean. that could be a possible speedup |
The non-regression test had passed: https://tests.stockfishchess.org/tests/view/66b293024ff211be9d4edd7e |
just wondering would it make sense if we move see out of position? after all it is an evaluation (static exchange evaluation) |
Syntactic sugar around Position::see_ge(), so that we can use the more readable pos.see(move) >= threshold instead of pos.see_ge(move, threshold), and similar readable code for the other comparison operators.
Patch tested locally for speed with both clang and gcc, no speed penalty found.
[Edit]
Non-regression test started here: https://tests.stockfishchess.org/tests/view/66b49f254ff211be9d4edf2a
No functional change.