Interleaved move pointers array

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
stegemma
Posts: 859
Joined: Mon Aug 10, 2009 10:05 pm
Location: Italy
Full name: Stefano Gemma

Interleaved move pointers array

Post by stegemma »

I like to experiment, even when my experiment lead to a "cul de sac". Tonight i've experimented a new idea. In my satana engine i've a class to store a single move and a fixed array for all moves. This class has some data: a flag+value 64 bit integer, an alfavalue to store result of last iteration and a little more. Profiling the code, a good 30% of the time is spent in sorting, specially in data moving. I thinked to avoid all this data copying using a moves pointers array, at the side of real moves data but this would need to handle some new pointers in move generation: the pointer to current move and the pointer to the array of the pointers (or use a single index, maybe). To avoid this, i've thinked to try "interleaved move pointers array". The idea is simple: in any move object i store... the pointer to the move itself. When i sort moves, i only sort the pointers. After quicksort, any move object can contains a pointer to another move. When i loop through moves, i only have to access the move pointed by the move pointer, instead of the move object itself.

Code: Select all


// before:
for(clsMove *pLoopMove=pFirstmove; pLoopMove<pLastMove; pLoopMove++)
{
   DebugMove(pLoopMove);
}

// after:

for(clsMove *ppLoopMove=pFirstmove, *pLoopMove=ppLoopMove->pMove; ppLoopMove<pLastMove; pLoopMove = (ppLoopMove++)->pMove)
{
   DebugMove(pLoopMove);
}

Of course this will requires a specialized quicksort function, to copy only the pointers in clsMove objects.

i think that interleaved move pointers could give better performance than using a separate array, because pointers reside in the same chunk of memory than pointed moves.

I'm debugging this new idea and i will give you some data about performance gain... or loss! :)
jordanbray
Posts: 52
Joined: Mon Aug 11, 2014 3:01 am

Re: Interleaved move pointers array

Post by jordanbray »

Sorting the pointer to the move may help in this case, it depends on the code.

One thing to keep in mind is that, (as I understand it), you have an array of pointers. This means that prefetch won't work in an intelligent manner. You can instruct the compiler to prefech the value associated with that pointer before you move, but keep in mind you may inadvertently speed up the sort, but then slow down the moves loop.

I'm not sure exactly why you need a full class to manage a move. I use a 16-bit integer, and it's /just/ enough space to store start square, end square, and promotion piece. I then have a 'move info' structure to store enough info to take the move back, but I don't think I ever create an array of that structure.

As an aside, I found that when sorting a small number of moves, quicksort had too much overhead. I actually switched to bubblesort (!) for a performance gain. (Of course, I split the moves up into multiple buckets before sorting.) Keep in mind O(n^2) is meaningless when you have a theoretical maximum on n. Everything is constant time, and quicksort has known performance problems with small lists.

Good luck!
User avatar
stegemma
Posts: 859
Joined: Mon Aug 10, 2009 10:05 pm
Location: Italy
Full name: Stefano Gemma

Re: Interleaved move pointers array

Post by stegemma »

jordanbray wrote:Sorting the pointer to the move may help in this case, it depends on the code.

One thing to keep in mind is that, (as I understand it), you have an array of pointers. This means that prefetch won't work in an intelligent manner. You can instruct the compiler to prefech the value associated with that pointer before you move, but keep in mind you may inadvertently speed up the sort, but then slow down the moves loop.

I'm not sure exactly why you need a full class to manage a move. I use a 16-bit integer, and it's /just/ enough space to store start square, end square, and promotion piece. I then have a 'move info' structure to store enough info to take the move back, but I don't think I ever create an array of that structure.

As an aside, I found that when sorting a small number of moves, quicksort had too much overhead. I actually switched to bubblesort (!) for a performance gain. (Of course, I split the moves up into multiple buckets before sorting.) Keep in mind O(n^2) is meaningless when you have a theoretical maximum on n. Everything is constant time, and quicksort has known performance problems with small lists.

Good luck!
In fact it gives almost no performance gain, the speed remains the same. You're right when you say that the move structure is too big, but i store in the move some extra information, that maybe could be handled in some different way. For sample, i store returned alphabeta value, just to sort moves at first ply but this information is useless at the other plyes.

For now this was just an experiment with no success but the idea of interleaved pointers maybe could help in some other application, so i share it.