Bitboards ?: C# vs C++

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
hgm
Posts: 28353
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Bitboards ?: C# vs C++

Post by hgm »

To get this clear: your 'entire board' is an array of 64 bytes, indexed by square numbers that run from 0 to 63, right? So when you mask it, that is not a single machine operation. It might be 8 operations on 64-bit words, because I don't think the compiler would be smart enough to use SIMD instructions for this.

I still have no clue how you proceed after that. You talk about 'searching' (past a blocker), but searching is in general a much slower process than finding, where you first do many steps that do not find what you search.
Chessnut1071
Posts: 313
Joined: Tue Aug 03, 2021 2:41 pm
Full name: Bill Beame

Re: Bitboards ?: C# vs C++

Post by Chessnut1071 »

hgm wrote: Fri Nov 19, 2021 7:23 pm To get this clear: your 'entire board' is an array of 64 bytes, indexed by square numbers that run from 0 to 63, right? So when you mask it, that is not a single machine operation. It might be 8 operations on 64-bit words, because I don't think the compiler would be smart enough to use SIMD instructions for this.

I still have no clue how you proceed after that. You talk about 'searching' (past a blocker), but searching is in general a much slower process than finding, where you first do many steps that do not find what you search.
It's more like 64 x 2 x 9 + 64 + 64. Actually, I don't mask the same way you do, I used that term, but, it's a simple array lookup with the KQRB[64,2,9] - all_pieces[ ] - and enemy_ check_mask[] arrays. The counter in front of each vector (ray) gives the legal steps terminated by the blocker. Two array lookups gives the move, direction, blocker and check. A third gives discovered check. Ent passant is a bit messy right now and I need to clean up pawn promotion. This approach is more than 50x faster than the one you described above.

I'd list the code, but, it's a GD mess and not cleaned up. In other words, it's not pretty right now, although it works.
Chessnut1071
Posts: 313
Joined: Tue Aug 03, 2021 2:41 pm
Full name: Bill Beame

Re: Bitboards ?: C# vs C++

Post by Chessnut1071 »

Chessnut1071 wrote: Fri Nov 19, 2021 7:50 pm
hgm wrote: Fri Nov 19, 2021 7:23 pm To get this clear: your 'entire board' is an array of 64 bytes, indexed by square numbers that run from 0 to 63, right? So when you mask it, that is not a single machine operation. It might be 8 operations on 64-bit words, because I don't think the compiler would be smart enough to use SIMD instructions for this.

I still have no clue how you proceed after that. You talk about 'searching' (past a blocker), but searching is in general a much slower process than finding, where you first do many steps that do not find what you search.
It's more like 64 x 2 x 9 + 64 + 64. Actually, I don't mask the same way you do, I used that term, but, it's a simple array lookup with the KQRB[64,2,9] - all_pieces[ ] - and enemy_ check_mask[] arrays. The counter in front of each vector (ray) gives the legal steps terminated by the blocker. Two array lookups gives the move, direction, blocker and check. A third gives discovered check. Ent passant is a bit messy right now and I need to clean up pawn promotion. This approach is more than 50x faster than the one you described above.

I'd list the code, but, it's a GD mess and not cleaned up. In other words, it's not pretty right now, although it works.
corrigendum
woops, KQRB is [64 x 8 x 2 x 9] + 64 + 64
User avatar
hgm
Posts: 28353
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Bitboards ?: C# vs C++

Post by hgm »

I have no idea what your all_pieces or enemy_check_mask arrays might contain, or for what purpose you might use those. Nor what KQRB might contain, and what it gets indexed with.
User avatar
lithander
Posts: 915
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: Bitboards ?: C# vs C++

Post by lithander »

dangi12012 wrote: Thu Nov 18, 2021 4:18 pm
lithander wrote: Thu Nov 18, 2021 2:51 pm
emadsen wrote: Wed Nov 17, 2021 5:45 pm I just realized System.Numerics.BitOperations class "provides utility methods for intrinsic bit-twiddling operations. The methods use hardware intrinsics when available on the underlying platform; otherwise, they use optimized software fallbacks." See the doc. So no need for preprocessor directives, assuming Microsoft's software fallback code performs well.
I also wasn't aware of that. I guess I should get to work on a bitboard engine... it won't become any more convenient than that. ;)
Sherlock - you found a 10 year old api.
System.Numberics.BitOperations was introduced with .Net Core 3.0 which released in 2019. :roll:
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
Chessnut1071
Posts: 313
Joined: Tue Aug 03, 2021 2:41 pm
Full name: Bill Beame

Re: Bitboards ?: C# vs C++

Post by Chessnut1071 »

hgm wrote: Fri Nov 19, 2021 7:59 pm I have no idea what your all_pieces or enemy_check_mask arrays might contain, or for what purpose you might use those. Nor what KQRB might contain, and what it gets indexed with.
enemy_check_mask = Kd5
where 1 = 8; 2 = - 8; 3 = 1; 4 = -1; 5 = 9; 6 = -9; 7 = 7; 8 = -7
50010070
05010700
00517000
33304444
00826000
08020600
80020060
00020006

all_pieces

each square either empty or piece type: 1 - 6 & 7 - 12

hope it helps
dangi12012
Posts: 1062
Joined: Tue Apr 28, 2020 10:03 pm
Full name: Daniel Infuehr

Re: Bitboards ?: C# vs C++

Post by dangi12012 »

lithander wrote: Fri Nov 19, 2021 8:17 pm
dangi12012 wrote: Thu Nov 18, 2021 4:18 pm
lithander wrote: Thu Nov 18, 2021 2:51 pm
emadsen wrote: Wed Nov 17, 2021 5:45 pm I just realized System.Numerics.BitOperations class "provides utility methods for intrinsic bit-twiddling operations. The methods use hardware intrinsics when available on the underlying platform; otherwise, they use optimized software fallbacks." See the doc. So no need for preprocessor directives, assuming Microsoft's software fallback code performs well.
I also wasn't aware of that. I guess I should get to work on a bitboard engine... it won't become any more convenient than that. ;)
Sherlock - you found a 10 year old api.
System.Numberics.BitOperations was introduced with .Net Core 3.0 which released in 2019. :roll:
:roll: :roll: :roll:
The question was about dotnet FRAMEWORK - and how to access bmi operations there. The answer is system.numerics nuget package.
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer
Chessnut1071
Posts: 313
Joined: Tue Aug 03, 2021 2:41 pm
Full name: Bill Beame

Re: Bitboards ?: C# vs C++

Post by Chessnut1071 »

dangi12012 wrote: Fri Nov 19, 2021 8:53 pm
lithander wrote: Fri Nov 19, 2021 8:17 pm
dangi12012 wrote: Thu Nov 18, 2021 4:18 pm
lithander wrote: Thu Nov 18, 2021 2:51 pm
emadsen wrote: Wed Nov 17, 2021 5:45 pm I just realized System.Numerics.BitOperations class "provides utility methods for intrinsic bit-twiddling operations. The methods use hardware intrinsics when available on the underlying platform; otherwise, they use optimized software fallbacks." See the doc. So no need for preprocessor directives, assuming Microsoft's software fallback code performs well.
I also wasn't aware of that. I guess I should get to work on a bitboard engine... it won't become any more convenient than that. ;)
Sherlock - you found a 10 year old api.
System.Numberics.BitOperations was introduced with .Net Core 3.0 which released in 2019. :roll:
:roll: :roll: :roll:
The question was about dotnet FRAMEWORK - and how to access bmi operations there. The answer is system.numerics nuget package.
I tried Syetem. Numerics, where do you get the nuget package? I have 4.7.3. and badly need bfs. Microsoft has a new 6.0 for 2022 which should have it, but, I haven't downloaded it yet.
User avatar
hgm
Posts: 28353
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Bitboards ?: C# vs C++

Post by hgm »

Chessnut1071 wrote: Fri Nov 19, 2021 8:49 pm
hgm wrote: Fri Nov 19, 2021 7:59 pm I have no idea what your all_pieces or enemy_check_mask arrays might contain, or for what purpose you might use those. Nor what KQRB might contain, and what it gets indexed with.
enemy_check_mask = Kd5
where 1 = 8; 2 = - 8; 3 = 1; 4 = -1; 5 = 9; 6 = -9; 7 = 7; 8 = -7
50010070
05010700
00517000
33304444
00826000
08020600
80020060
00020006

all_pieces

each square either empty or piece type: 1 - 6 & 7 - 12

hope it helps
OK, so all_pieces is the mailbox board, and enemy_check_mask a board size table containing the number of the direction you have to move in to hit a king on d5. (Do you have 64 such tables?) The latter does not seem useful for knowing where a slider gets blocked.

Now what is in KQRB? And what is it indexed by? I assume 64 is the square of origin, and the 2 is color? What do you use in the 9 dimension?
Chessnut1071
Posts: 313
Joined: Tue Aug 03, 2021 2:41 pm
Full name: Bill Beame

Re: Bitboards ?: C# vs C++

Post by Chessnut1071 »

hgm wrote: Fri Nov 19, 2021 9:35 pm
Chessnut1071 wrote: Fri Nov 19, 2021 8:49 pm
hgm wrote: Fri Nov 19, 2021 7:59 pm I have no idea what your all_pieces or enemy_check_mask arrays might contain, or for what purpose you might use those. Nor what KQRB might contain, and what it gets indexed with.
enemy_check_mask = Kd5
where 1 = 8; 2 = - 8; 3 = 1; 4 = -1; 5 = 9; 6 = -9; 7 = 7; 8 = -7
50010070
05010700
00517000
33304444
00826000
08020600
80020060
00020006

all_pieces

each square either empty or piece type: 1 - 6 & 7 - 12

hope it helps
OK, so all_pieces is the mailbox board, and enemy_check_mask a board size table containing the number of the direction you have to move in to hit a king on d5. (Do you have 64 such tables?) The latter does not seem useful for knowing where a slider gets blocked.

Now what is in KQRB? And what is it indexed by? I assume 64 is the square of origin, and the 2 is color? What do you use in the 9 dimension?
The KQRB board: below is the code for squares 30 and 31. In the example square 30, or b4, has 4 moves north +8, 38,46,54 & 62, 3 moves south, 1 move west, and 6 moves east, 1 move north west, 3 moves south east, 4 moves north east and 1 move south west.

if the square > o the vector is terminated, capture piece and direction are saved along with check from the check_mask. Discovered check combines piece board with the check mask, using the direction (1-8) with the piece type 3,4 or 5.

30,4,38,46,54,62,0,0,0,
30,3,22,14,6,0,0,0,0,
30,1,31,0,0,0,0,0,0,
30,6,29,28,27,26,25,24,0,
30,1,39,0,0,0,0,0,0,
30,3,21,12,3,0,0,0,0,
30,4,37,44,51,58,0,0,0,
30,1,23,0,0,0,0,0,0,

31,4,39,47,55,63,0,0,0,
31,3,23,15,7,0,0,0,0,
31,0,0,0,0,0,0,0,0,
31,7,30,29,28,27,26,25,24,
31,0,0,0,0,0,0,0,0,
31,3,22,13,4,0,0,0,0,
31,4,38,45,52,59,0,0,0,
31,0,0,0,0,0,0,0,0,

I'm not sure if this follows anybody's code, it just made logical sense to me. So, where am I wrong?