Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: High performance move generation

Author: Bas Hamstra

Date: 06:52:53 11/19/99

Go up one level in this thread


On November 18, 1999 at 12:41:52, Ratko V Tomic wrote:

>>
>> . *NextDirection
>> . *Continue
>>
>> *Continue contains the squares of all sliding moves in one specific direction.
>> NextDir contains the first square of the next direction.
>>
>> No testing needed if you are off the board and no adding of offsets. Simply
>> "dereferencing" pointers which is pretty quick.
>
>It is quicker to use an add value for a given direction and a count how many
>times to repeat the add than to dereference a pointer to obtain the next offset.
>Namely the board offsets and the add value, once read into the auto variables
>can be optimized by the compiler as register variables (which MSVC will do),
>while picking the next offset from an array requires that code go to memory to
>produce the next offset (i.e. it cannot be optimized by compiler as a register
>variable since compiler can't assume safely that it won't change; for auto
>variables it can assume it won't change and it will keep such variables in
>registers whenever possible).

I agree. I generate non captures the way I described. But captures are generated
differently, based on incrementally updated attacks, which are done more or less
the way you described below. To change my non capture generation scheme wouldn't
have a big impact on overall program speed, I think. My NextCapture() is simply
a LastOne(AttacksOnBiggestPiece), where Attacks are available at ANY time.
PseudoAttacks, in fact.

>To summarize, in the case of add value you would have variables: delta, count
>and board ptr, while in the case of board offsets in an array, you have list
>ptr, count (or a terminating value in the list which is even more expensive
>since it too has to be read out of memory instead of register) and board ptr. In
>the first case all 3 variables can be in registers, in the second case only 2
>can be in registers (in the code from the earlier post, without count and using
>list value as loop terminator, only 1 can be register variable).
>
>
>Even better than count is a switch statement where the count serves as a
>dispatch value into a sequence of back to back add, check board at the offset,
>add, ... etc, so that the scan of empty squares won't cause jump or loop-back
>instruction (which are more expensive than straight fall through). In assembly
>language one can easily code this so that (piece,source_square) pair of values
>retreives a pointer to a code label which has the right number of directions and
>steps each direction coded to execute without jumps or loops and to change the
>direction (on default end of direction), all in a single block of a fall through
>code.

I think you can as well do this in C with the good old goto?

Anyway I finally became convinced that the importancy of the speed of the
movegenerator is modest, unless you want to make a Fritz. Like someone said
here: you can be ultrafast, and that's good, but then you constantly have to
worry about code you want to add. The slightest pieces of code already spoil
your tremendous NPS. That restricts you. If you do a reasonable leaf eval it
will always be the eval that eats most of the ticks...


Regards,
Bas Hamstra.















This page took 0.01 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.