Doesn't the compiler do that automatically? How else could it store them? If the struct contains an int64 for the signature, C alignment rules force the address to be aligned with 8-byte boundaries, so if the entry is not larger than 16 byte (which it almost never is), all other items must be packed in the second 8-byte machine word.
Or is it that you first make a copy of that part of the struct before accessing any of the individual fields? I guess accessing them separately is indeed ill-advised in a multi-threaded environment, and one should always make a copy first.
This guarantees that the score, move, flags etc. all belong with each other. But does that of any real help when they do not belong to the sought position? If I have a score that is completely wrong because it comes from another position, is there really any value in knowing correctly that it is (say) an upper bound? It seems to me that when you got it wrong, you got it wrong. There doesn't seem much benefit in getting it
consistently wrong.
It would actually be much better if the key were distributed over the two int64 words of the entry. E.g. declare
Code: Select all
typedef struct {
int16 move;
int16 score;
int32 key[2];
char flags;
char depth;
char age;
char whatever;
} HashEntry;
If you align the hash table with cache-line boundaries this would make key[0] fall in the first word, and key[1] in the second word. You could then (after copying the entire entry) compare the key as
Code: Select all
if(hashKey = *(int64 *)hashEntry.key) ...
to read the key[2] array as a single 64-bit quantity. If the two halves of the key would come from different entries because of the race, they are unlikely to match any other key.