Question about how to fix some efficient memory layout of large 1d-structures?

thx for your response.
As much, as I understand your curiosity and willingness, to embark in thoughts about the content of data-entries in the arrays. There is literally nothing uncertain about that part, for me. I am merely trying to implement efficient containers to store and retrieve individual data-elements and I’m happy, opening another thread, explaining all the details of the content, but for the sake of the questions I posted here, and for solving the issues I’m having, the content is literally irrelevant. :wink:

I’m happy giving some background, though, just to motivate, why I’m even needing these containers.

  • One Container / Hashtable (the largest) will be a a transposition-table, storing some of the positions, encountered in the search-tree, of what is, essentially a (much refined) alpha-beta - search. But since there will be a few M nodes being visited, during the search, within short time-spans (seconds), only a portion of those positions will make it into the hashtable (those, which belong to the currently best evaluated line, for either side, and which have the highest chances, enabling the pruning of the search-tree in other parts of the tree, but which also traverse the same position). The encoding of “position” is achieved via zobrist-hashing, which can be generated much faster, than any run-lenght encoding, etc., and serves as the hash-key (index into the table), at the same time. You can find a rough sketch, of how entries in the transposition-table will look like, in this post. Overall, the hashtable is a global structure, where entries are persistent, even across moves, as positions are sometimes precalculated at great depth and their evaluation might stay relevant or they may even reoccur (due to move-ordering, especially in phases of the game, with few captures).

  • The above mentioned Zobrist-hashing is being calculated by having ~750 pre-computed (random) numbers, one for each piece on every square: 64 sq. x 2 colors x 6 types of pieces = 768 + castling-rights and a few other details. When a move is being made (simulated in the search!), the current’s position zobrist-hashkey is simply xor-ed with 2…3 of those numbers. One for the piece, leaving a sq., one for the same piece, moving to another sq. + potentially one more, for the latter target-square & a potentially captured piece, in case it is a capturing move. Etc.
    These keys are also stored in a lookup-table. In this case, it is a very small table (~750 x 8 bytes = ~6 KB). Kind of a lookup-table for the building-blocks of hashkeys to the first table. :wink:

  • Then there are other hashing functions, being used, especially for the move-generation of sliding pieces (rooks, bishops, queens), which are (like the zobrist-hashkeys) pre-computed and being looked-up, during a game-tree-search, for quick move-generation. See here, especially, for a good intro, into fancy magic bitboards, which can be understood in terms of minimal perfect hash-functions. Those tables are still much smaller, than the transposition-table, but do exceed L1-cache & L2-cache, even on modern machines, sadly, still. (~820 KByte).

  • Those are probably the most prominent tables, but then there are a bunch of others, acting as parameter-lookups for positonal bonuses of pieces (depending on their board-position) or even whole arrangements of piece-ensembles (like pawn-structures, etc.). But this data is more flexible, to either be coded or for pre-computed data to be looked up. It is essentially always a tradeoff between costs of calculations and costs for alternative lookups in precomputed tables. Interestingly, this tradeoff itself is usually a parameter, which can be tuned, according to certain criteria. For example, a transposition-table can often speed up search by a almost a factor 4…5x, in the endgame, but it is only marginally useful, in the opening, etc., etc.

  • A whole other story are Endgame tablebase - Wikipedia. I think, at the moment, they are still working on 8-piece-endgame - tablebases, but this might get solved, in the foreseeable future, but this is not, what I’m trying to do here. I will eventually support endgame-tablebases, and I’m sure, I’ll also provide a cache for some of that data, but they will have to reside on disk, as even the (“only”) 6-piece-tables are ~150GB large - and this is with some very efficient encoding, already. :wink:

…I hope, that helped motivating my efforts a bit.

For the questions, I’m having, regarding implementing a general structure, of such tables, in julia: ALL access, to those tables will only ever be random, i.e. no iteration of entries, in any way. No calculation (like matrix-multiplication, broadcasts, or whatnot) Just plain access to individual entries of 1d-tables via their unique index. There is really not more to say, about it. Only read-access, in some cases, Read-write, in others.

1 Like