Pradu wrote:bob wrote:I'm not sure I follow. I've always done x-ray attacks using rotated bitboards with no effort. Ditto for pins, where I need that in GenerateCheckEvasions()... And even doing all that, I got a zero speed increase...
Well it is atleast as fast as rotated according to your tests. Can you post a quick profile of Crafty with magics here? It could be that generating move bitboards isn't done much timewise in Crafty. As for comparing versitality of rotated and magic approaches:
Let me guess that you have extra rotated xray-databases (RmovesXray[64][64], BmovesXray[64][64]) to do fast xrays? Even if one can do xrays with rotated, it isn't versitle. One can probably get away with it for checking pins but for anything complex it won't work because you can't xray selectively.
No, I just look at the diagonals to see if a sliding piece is beyond the piece in question (see swap.c and SwapXray() in it to see what I mean)...
Some things you can do faster with magics are like finding pinners to your pieces (not opponents pieces as well).
- Code: Select all
possiblePinned=Bmoves(pos->KingPos[side],pos->AllPieces)&pos->PiecesSide[side];
pinners=Bmoves(pos->KingPos[side],pos->AllPieces^possiblePinned)
& ((pos->Pieces[B]|pos->Pieces[Q])&pos->PiecesSide[!side]);
Take the example of battery attacks which you can't do with rotated at all.
- Code: Select all
//Battery attacks including regular attacks
batteryattacksB=Bmoves(square,occupancy&~diagonalSliders[myside])
Tell me how one would do battery with rotated bitboards without any expensive LastOne/FirstOne calls and without 6 additional rotated bitboards for bishops+queens and rooks+queens. (You'll need to add 3 extra rotated bitboards for every case to generate selective xray attacks).
In Swap() for example, After I "use" a queen or bishop to capture on a diagonal, I just look the other direction from that queen/bishop to see if there is another one back there. Very cheap...
Or how about multiple xrays which might be required in SEE?
See above. Once I use a piece, I do a very quick (one line) check to see if there is another slider behind it. And once I use that one, I look again. I don't really need to find all battery pieces at once, although I suppose I might find a way to use that reasonably in the SEE code. However, SEE is not a major part of my total time anyway...
The thing is, one can't avoid FirstOne/LastOne calls completely to do some basic things with rotated bitboards...unless you can show me otherwise.
At least in my SEE stuff I don't need any MSB/LSB stuff to find batteries at all... I do use MSB/LSB to pick off each individual piece as it participates in the capture "party"...
In any case, anything you can do with rotated, you can do with magics -- and then some.
There are complications. Sometimes I only want a specific diagonal. With rotated I can look that up. With magic I have to compute both and then remove one, which is not so easy with diagonals. I also use rank attacks or file attacks for things like asking if two rooks are connected on the 7th... Again I have to and off 1/2 the data the magic stuff gives me...
Here's my latest testing going back and modifying things to use your smaller tables:
32bit:
log.001: time=1:45 mat=0 n=93585150 fh=90% nps=883K
log.002: time=1:47 mat=0 n=93585150 fh=90% nps=869K
so there magic is actually slower, probably those 64 bit multiples that are killers on a 32 bit machine...
64bit:
log.001: time=1:19 mat=0 n=93585150 fh=90% nps=1.2M
log.002: time=1:19 mat=0 n=93585150 fh=90% nps=1.2M
No difference there at all. Looks like the 2mb version is actually faster in 32 bit mode and about equal on the 64 bit xeons we have. I'll try to run some opteron tests later...