lithander wrote: ↑Sat Jul 03, 2021 2:18 pm
So I'm also in favor for version 3.
Darn. That took a lot of convincing. Again
Now I'm wondering what number of buckets are optimal.
In Rust, it's hard to test how big a struct is, because Rust can re-arrange and pad the struct members as it sees fit, to optimize the compilation. Sometimes I get really strange results. I put 17 bytes into a struct, and I would expect it to be rounded up to the next multiple of 8, which is 24, but the size_of() function says 16, so it is obviously "collapsing" / interleaving bytes in the struct somehow. I've also got a struct somewhere that contains only 12 bytes, which is already a multiple of 3, but Rust pads it to be 24 bytes.
I am assuming it doesn't do that just for fun. It makes me wonder if "keep your entire bucket under 64 bytes" is still applicable when using Rust, because the compiler does exactly what it wants.
I could use it to leave the structs alone and represent it as C would do, with the given order of the members, by using "repr(C)" on it. That is not recommended however. "repr(C)" is intended to make a C-type struct in case you need to interface with C-code that either takes or returns structs.
I now use 4 entries/bucket (a bucket sits at an index, obviously). The TT generally is 256 MB, because CCRL uses that size, even though the engine only gets it filled up half-way in 10s+0.1s testing. Maybe I should test versions with 3 and 2 buckets to see if they are faster.
Also the question... you can have so many entries per bucket that you end up with a "vertical" TT... where there is only one index/bucket with all the entries in it. I wonder where the point lies where an increase in entries/bucket is detrimental to TT performance. As you increase the number of entries/bucket, it takes more and more time trawling through all the entries to find the one to replace. Same as with the killers: if you have more than 2, maybe 3, keeping them all unique costs so much time that the advantage of the extra killer(s) is negated by the time it costs to maintain them.
hgm wrote: ↑Sat Jul 03, 2021 12:31 pm
I am biased in favor of (3), as it does not only solve the PV problem in the first branch, but increases the efficiency of the TT through the entire tree.
So you think having 2 buckets and aging (which I don't have yet) is enough to not get the PV-move be overwritten in the TT; i.e., it's not useful to re-stuff the PV into the TT?
lithander wrote: ↑Sat Jul 03, 2021 2:18 pm
You don't have to clear the table and you don't have to keep track of the age. You just have to toggle between mapping A and B from time to time and I would expect to do it whenever a search concludes. (Where you would also consider clearing the TT if you'd do such thing)
Interesting idea... in my tests, clearing the TT and not clearing the TT did not really make a difference when using a 256 MB TT with buckets at a 10s + 0.1s time control. Even using more entries/bucket, or no buckets at all didn't really make a difference. The largest difference from these tests was 7 Elo, but with a 10 Elo error bar.
Currently with one bucket my Index is computed like this:
Are you putting a bucket "across" two indices, if I'm seeing this correctly?
In my case, I actually have a "Bucket" struct, which sits at the TT index, and it contains an array with N entries. (Where N >= 1, at compile time.)
You just have to make sure tick_tock alternates between 'true' and 'false' between searches. While the old PV would still be there when you need it (at the start of the search) it then get's flushed out of the system eventually as it is now sitting in the always replace bucket.
Does that make sense? Or am I overlooking something?
It's an interesting idea. You're basically clearing half the TT for each search.
To me, it still feels strange to clear any part of the TT during search, except for overwriting entries that are not useful anymore... Maybe you could try it and see if it's an improvement. I doubt it would be a big improvement when playing super-fast games. The TT doesn't seem to affect those games much. Just _having_ a TT of a somewhat decent size near the end game seems to be enough.