Check legality of a move without making it... even a human 'makes' a move in their head to check legality, so I'll have to look at the Stockfish code (which, to be honest, I find quite horrible) to see how this works.Terje wrote: ↑Sat Apr 11, 2020 2:23 pmA third possiblity is to have a function which checks the legality of a move without making it. SF uses this in search before making the move so there is no chance it needs to be taken back immediately after making it, and the same could be used to get something closer to bulk counting. This could be a speedup of perft depending on how expensive it is to compute, and, since SF uses it, probably good for the chess engine part.
By the way; I think HGM and Fabian were right; apart from cutting out superfluous code, watching for things such as unneeded memory allocations or replacing X with faster Y (where Y is more efficient or does less to reach the same conclusion as X, such as minimax vs a/b), optimization down to the statement level is completely and utterly useless.
I just added a function to Rustic which needs to initialize a variable in "GameState" by counting some stuff on the board (similar to material count). It is only called ONCE, during board initialization, and has NOTHING to do with perft... and still my perft 7 time rose from 86 to 92 (!) seconds.
Therefore I'll adopt HGM's approach; only optimize by replacing code with code that is objectively faster (such as replacing bubble-sort with qsort for example), and cut out inefficiencies. I'm not going to try and optimize down to the statement order again, if this optimization can be disrupted by adding a completely unreleated function somewhere else in the program, or even by compiling with a different version of Rust or for a different CPU. (Or even by running the binary on the same CPU but on a different system...)
it seems all of the optimization tricks I have in my toolkit for optimizing things such as PLC's and microcontrollers are useless when it comes to x64 compilers and CPU's.