Author: Gerd Isenberg
Date: 07:47:09 01/21/03
Go up one level in this thread
On January 21, 2003 at 10:11:08, Bas Hamstra wrote:
>On January 21, 2003 at 06:04:56, José Carlos wrote:
>
>>On January 21, 2003 at 05:46:37, Bas Hamstra wrote:
>>
>>>Hi Russell,
>>>
>>>Question: Why do you calculate KnightAttacks the way you do? Why not simply
>>>
>>> KnightAttacks(Sq) = KnightAttMask[Sq];
>>>
>>>One memory lookup in a small precalculated table KnAtt[64] should be much much
>>>faster. For the rest I am interested to test the speed of the C-style fill
>>>routines against rotated BB. Will be slower, but how much?
>>>
>>>Bas.
>>
>> It can be useful for any calculation you can do in parallel. For example, you
>>might want to know which of your pieces are attacked by opponent light pieces.
>>For simplicity, let's suppose you're only interested in knight attacks. Then
>>you do:
>>
>> KinghtAttacks(MyPieces) & OpponentKnights
>>
>> If don't know if it is faster than extracting the bits from OpponentKnights,
>>doing the table lookup and matching it against MyPieces, but it's simpler.
>
>No, the table lookup is practically FREE. Remember this is just a small table,
>that basically remains in cache. The computation OTOH does a big number of
>expensive shifts for nothing. Also I fail to see why it is simpler...
>
>Bas.
Hi Bas,
for one (or two) Knight it's obvious, that a lookup is superior.
In Jose's sample you have to traverse (a bitscan-loop) over all MyPieces to "or"
all the Knight-Attacks from every piece square via lookup.
But in this case it is of course smarter to traverse over all opponent Knights
(most often not more than two ;-) to or all attacks via lookup anding finally
with own pieces.
Anyway for some reasons (eg. progressive Knight mobility) it is nice to have a
fill-based routine working with a set for multiple (virtual) knights.
I think Russel's routine is faster to implement (even if it introduces few more
dependencies), by first shifting one and two left/right with wrap anding, and
then shifting one resp. two up and down, that saves four ands.
With MMX you save the right wrap ands due to paddb instruction (packed add
byte).
Regards,
Gerd
--------------------------------------------------------
// input: mm1 knightBB
// output: mm0 knightAttacks
//============================
void getKnightAttacksMMX()
{
__asm
{
pxor mm4, mm4 ; 0x0000000000000000
pcmpeqd mm7, mm7 ; 0xffffffffffffffff
movq mm2, mm1 ; left
psubb mm4, mm7 ; 0x0101010101010101
psubb mm7, mm4 ; 0xfefefefefefefefe notA
pand mm2, mm7 ; clear left a-file before shift
paddb mm1, mm1 ; right
psrlq mm2, 1 ; left
movq mm3, mm1
paddb mm1, mm1 ; 2right
por mm3, mm2 ; left|right
movq mm0, mm3 ; left|right
pand mm2, mm7 ; clear left a-file before shift
psrlq mm3, 16 ; left|right -> 2down
psllq mm0, 16 ; left|right -> 2up
psrlq mm2, 1 ; 2left
por mm0, mm3
movq mm3, mm1
por mm3, mm2 ; 2left|2right
movq mm2, mm3 ; 2left|2right
psllq mm3, 8 ; 2left|2right -> up
psrlq mm2, 8 ; 2left|2right -> down
por mm0, mm3
por mm0, mm2
}
}
This page took 0 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.