Help improving this code ?!

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

MahmoudUthman
Posts: 234
Joined: Sat Jan 17, 2015 11:54 pm

Help improving this code ?!

Post by MahmoudUthman »

This is the code I use for make/unmake :

Code: Select all


static U64 SBackup[MaxDepth][16];
static U64 CRBackup[MaxDepth][2];
static U64 PositionKeyBackUp[MaxDepth];
static unsigned int LastMoveDPushSQBackup[MaxDepth];
static U64 HalfMoveClockBackUp[MaxDepth];
static Score PSQTScore;
static Score PSQTScoreBackUp[MaxDepth];

static int ply = 0;
static U64 BitBoards[16];
static U64 HalfMoveClock = 0ULL;
static U64 GameRecordCounter = 0ULL;
static U64 Positionkey = 0ULL;
static U64 GameRecord[512];
//Junk,Real
unsigned int DoublePushSQ[2] = { 0U,0U };
BB TypeBoard[64 + MaxDepth];
Color STM = White;
make:

Code: Select all

void MakeMove(const Move& __restrict M)
{
	HalfMoveClockBackUp[ply] = HalfMoveClock;/
	HalfMoveClock++;

	std::memcpy(SBackup[ply], BitBoards, 16 * sizeof(U64));

	PositionKeyBackUp[ply] = Positionkey;
	CRBackup[ply][0] = CastleRights[0];
	CRBackup[ply][1] = CastleRights[1];

	PSQTScoreBackUp[ply] = PSQTScore;

	Color NTM = Color(7 - STM);
	unsigned int From = M.From, To = M.To;
	BB PT = TypeBoard[From];

	PSQTScore += psq[STM ? 1 : 0][PT][To] - psq[STM ? 1 : 0][PT][From];


	LastMoveDPushSQBackup[ply] = DoublePushSQ[1];
	if (DoublePushSQ[1] != 0) Positionkey ^= GetEnpassantZobrist();

	DoublePushSQ[1] = 0UL;
	TypeBoard[64 + ply] = TypeBoard[To];
	U64 ToMask = 1ULL << To;
	U64 FromMask = ~&#40;1ULL << From&#41;;
	BitBoards&#91;Occupied&#93; &= FromMask;
	BitBoards&#91;STM + PT&#93; &= FromMask;
	BitBoards&#91;Occupied&#93; |= ToMask;
	BitBoards&#91;NTM + Enemy&#93; &= FromMask;
	BitBoards&#91;NTM + Enemy&#93; |= ToMask;
	Positionkey ^= ZobristSide;
	size_t USTM = STM & 1ULL, UNTM = NTM & 1ULL;
	Positionkey ^= Zobrist&#91;PT&#93;&#91;USTM&#93;&#91;From&#93;;
	Positionkey ^= GetCatsleZobrist&#40;);
	switch &#40;M.Type&#41;
	&#123;
	case NORMAL&#58;
		if &#40;BB CapturedPiece = TypeBoard&#91;64 + ply&#93;)
		&#123;
			HalfMoveClock = 0ULL;
			Positionkey ^= Zobrist&#91;CapturedPiece&#93;&#91;UNTM&#93;&#91;To&#93;;
			PSQTScore -= psq&#91;NTM & 1&#93;&#91;CapturedPiece&#93;&#91;To&#93;;
		&#125;
		//HalfMoveClock = HalfMoveClock&&#40;0ULL - &#40;PT != Pawn&#41;);
		if &#40;PT == Pawn&#41; HalfMoveClock = 0ULL;
		Positionkey ^= Zobrist&#91;PT&#93;&#91;USTM&#93;&#91;To&#93;;//Add To
		BitBoards&#91;STM + PT&#93; |= ToMask;
		DoublePushSQ&#91;(&#40;From^To&#41; == 16U&#41;&&#40;PT == Pawn&#41;&#93; = To;
		if (!PT&#41; CastleRights&#91;STM & 1U&#93; = 0ULL;
		BitBoards&#91;STM + Enemy&#93; &= ~ToMask;
		BitBoards&#91;NTM + TypeBoard&#91;64 + ply&#93;&#93; &= ~ToMask;
		BitBoards&#91;NTM + Enemy&#93; &= ~BitBoards&#91;STM + King&#93;;
		CastleRights&#91;0&#93; &= BitBoards&#91;Black + Rook&#93;;
		CastleRights&#91;1&#93; &= BitBoards&#91;White + Rook&#93;;
		break;
	case PROMOTION&#58;
		HalfMoveClock = 0ULL;
		if &#40;BB CapturedPiece = TypeBoard&#91;64 + ply&#93;)
		&#123;
			Positionkey ^= Zobrist&#91;CapturedPiece&#93;&#91;UNTM&#93;&#91;To&#93;;
			PSQTScore -= psq&#91;NTM & 1&#93;&#91;CapturedPiece&#93;&#91;To&#93;;
		&#125;
		PT = BB&#40;M.PromoType + 2&#41;;
		Positionkey ^= Zobrist&#91;PT&#93;&#91;USTM&#93;&#91;To&#93;;
		BitBoards&#91;STM + PT&#93; |= ToMask;
		BitBoards&#91;STM + Enemy&#93; &= ~ToMask;
		BitBoards&#91;NTM + TypeBoard&#91;64 + ply&#93;&#93; &= ~ToMask;
		CastleRights&#91;0&#93; &= BitBoards&#91;Black + Rook&#93;;
		CastleRights&#91;1&#93; &= BitBoards&#91;White + Rook&#93;;
		PSQTScore += psq&#91;STM & 1&#93;&#91;PT&#93;&#91;To&#93; - psq&#91;STM & 1&#93;&#91;Pawn&#93;&#91;To&#93;;
		break;
	case ENPASSANT&#58;
		HalfMoveClock = 0ULL;
		&#123;
			const auto dpSq = LastMoveDPushSQBackup&#91;ply&#93;;
			Positionkey ^= Zobrist&#91;PT&#93;&#91;UNTM&#93;&#91;dpSq&#93;;
			Positionkey ^= Zobrist&#91;PT&#93;&#91;USTM&#93;&#91;To&#93;;
			BitBoards&#91;Occupied&#93; &= ~&#40;1ULL << dpSq&#41;;
			PSQTScore -= psq&#91;NTM & 1&#93;&#91;Pawn&#93;&#91;dpSq&#93;;
			BitBoards&#91;NTM + PT&#93; &= BitBoards&#91;Occupied&#93;;
			BitBoards&#91;STM + Enemy&#93; &= BitBoards&#91;Occupied&#93;;
			BitBoards&#91;STM + PT&#93; |= ToMask;
			TypeBoard&#91;dpSq&#93; = Null;
		&#125;
		break;
	case CASTLING&#58;
		Positionkey ^= Zobrist&#91;King&#93;&#91;USTM&#93;&#91;&#40;NTM * 8&#41; + 4&#93;;
		Positionkey ^= Zobrist&#91;Rook&#93;&#91;USTM&#93;&#91;To&#93;;
		BitBoards&#91;Occupied&#93; &= ~BitBoards&#91;STM + King&#93;;
		&#123;
			unsigned int KingTo = &#40;From + To + 1&#41; >> 1;
			Positionkey ^= Zobrist&#91;King&#93;&#91;USTM&#93;&#91;KingTo&#93;;
			BitBoards&#91;STM + King&#93; = 1ULL << KingTo;
			PSQTScore += psq&#91;STM & 1&#93;&#91;King&#93;&#91;KingTo&#93; - psq&#91;STM & 1&#93;&#91;King&#93;&#91;&#40;NTM * 8&#41; + 4&#93;;
		&#125;
		BitBoards&#91;STM + PT&#93; |= ToMask;
		BitBoards&#91;Occupied&#93; |= BitBoards&#91;STM + King&#93;;
		CastleRights&#91;STM & 1U&#93; = 0ULL;
		break;
	default&#58;
		break;
	&#125;
	Positionkey ^= GetCatsleZobrist&#40;);
	if &#40;DoublePushSQ&#91;1&#93; != 0&#41; Positionkey ^= GetEnpassantZobrist&#40;);
	GameRecord&#91;++GameRecordCounter&#93; = Positionkey;
	ply++;
	BitBoards&#91;Empty&#93; = ~BitBoards&#91;Occupied&#93;;
	STM = NTM;
	TypeBoard&#91;From&#93; = Null;
	TypeBoard&#91;To&#93; = PT;
&#125;
Unmake:

Code: Select all

void UnMakeMove&#40;const Move& __restrict M&#41;
&#123;
	std&#58;&#58;memcpy&#40;BitBoards, SBackup&#91;--ply&#93;, 16 * sizeof&#40;U64&#41;);
	GameRecordCounter--;
	HalfMoveClock = HalfMoveClockBackUp&#91;ply&#93;;

	Positionkey = PositionKeyBackUp&#91;ply&#93;;
	CastleRights&#91;0&#93; = CRBackup&#91;ply&#93;&#91;0&#93;;
	CastleRights&#91;1&#93; = CRBackup&#91;ply&#93;&#91;1&#93;;

	PSQTScore = PSQTScoreBackUp&#91;ply&#93;;

	DoublePushSQ&#91;1&#93; = LastMoveDPushSQBackup&#91;ply&#93;;
	STM = Color&#40;7 - STM&#41;;
	unsigned int From = M.From, To = M.To;
	TypeBoard&#91;From&#93; = TypeBoard&#91;To&#93;;
	if &#40;M.Type == ENPASSANT&#41; TypeBoard&#91;DoublePushSQ&#91;1&#93;&#93; = Pawn;
	else if &#40;M.Type == PROMOTION&#41;TypeBoard&#91;From&#93; = Pawn;
	TypeBoard&#91;To&#93; = TypeBoard&#91;64 + ply&#93;;
&#125;
I wrote it a couple of years ago when I was just starting to program so it isn't in top shape , I Know that premature optimization isn't a good thing and that the speed gain from optimizing this won't affect the engine's elo much if at all , but the problem I'm facing is that when I wrapped my code inside a "position" class those parts slowed down considerably "~10%:20%", C++ isn't my "native" language and I understand that abstraction comes with a cost -"but not a huge one"- but I believe that the cause is something I'm doing wrong here , the reset of the functions don't suffer from the same performance degradation , even the move generator is the same speed .
Henk
Posts: 7220
Joined: Mon May 27, 2013 10:31 am

Re: Help improving this code ?!

Post by Henk »

10-20% is nothing. You are just wasting your time. (Like I do all day)
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Help improving this code ?!

Post by Sven »

Don't know whether it is related to your problem but a line like this:

Code: Select all

BitBoards&#91;NTM + TypeBoard&#91;64 + ply&#93;&#93; &= ~ToMask;
looks *very* suspicious, since TypeBoard is an array of bitboards ...

Do you swear that there will "never ever" be an array bounds overflow?

Edit: ok, I see that I misinterpreted the meaning of "BB", in fact it seems to be a piece type, not a bitboard, despite the name ... But nevertheless, I get the feeling that the whole "TypeBoard" stuff is unintuitive (array index "64 + ply"?). And I would not be surprised if your actual problem were related to some unintuitive code.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Help improving this code ?!

Post by Sven »

Which variables are now members of your class "Position"? Those listed above as "static" (so they are now no longer static)?
Henk
Posts: 7220
Joined: Mon May 27, 2013 10:31 am

Re: Help improving this code ?!

Post by Henk »

They always told me that object oriented programming is not for free. Calling a virtual method is like dereferencing a pointer to a function. So if you want to code more efficiently use C instead of C++. No nonsense with virtual tables.
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: Help improving this code ?!

Post by AlvaroBegue »

Henk wrote:They always told me that object oriented programming is not for free. Calling a virtual method is like dereferencing a pointer to a function. So if you want to code more efficiently use C instead of C++. No nonsense with virtual tables.
This doesn't make any sense. Why is the cost of calling virtual functions an argument for using a different language? If you don't want to pay the cost of calling virtual functions, don't use virtual functions.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Help improving this code ?!

Post by Sven »

Henk wrote:They always told me that object oriented programming is not for free. Calling a virtual method is like dereferencing a pointer to a function. So if you want to code more efficiently use C instead of C++. No nonsense with virtual tables.
Henk, please ... how can we prevent you from writing nonsense in a serious thread where someone is looking for help?
Henk
Posts: 7220
Joined: Mon May 27, 2013 10:31 am

Re: Help improving this code ?!

Post by Henk »

AlvaroBegue wrote:
Henk wrote:They always told me that object oriented programming is not for free. Calling a virtual method is like dereferencing a pointer to a function. So if you want to code more efficiently use C instead of C++. No nonsense with virtual tables.
This doesn't make any sense. Why is the cost of calling virtual functions an argument for using a different language? If you don't want to pay the cost of calling virtual functions, don't use virtual functions.
Then it is more object based programming. Yes that's possible too.

I don't know if it isn't always using virtual tables whether there are virtual methods defined or not. I would be surprised if inheritance is for free.
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: Help improving this code ?!

Post by AlvaroBegue »

Henk wrote:I don't know if it isn't always using virtual tables whether there are virtual methods defined or not. Don't even know how inheritance is implemented. I think you need at least an extra pointer from an object to it's parent.
It's OK to be ignorant about something. But then you shouldn't go around giving advice about it.

No, C++ doesn't use vtables if there aren't virtual methods. Inheritance is implemented in several different ways, which you can look up on the web. You generally don't need a pointer to the parent, unless you are using virtual inheritance.

Personal opinion: If you want to live a happy life, don't use virtual inheritance, multiple inheritance or non-public inheritance. Use simple, non-virtual, public inheritance, and only to get polymorphic behavior, and only when inheritance expresses an "IS-A" relationship.

By the way, I have never used virtual functions or inheritance in a chess engine.
MahmoudUthman
Posts: 234
Joined: Sat Jan 17, 2015 11:54 pm

Re: Help improving this code ?!

Post by MahmoudUthman »

Sven Schüle wrote:Don't know whether it is related to your problem but a line like this:

Code: Select all

BitBoards&#91;NTM + TypeBoard&#91;64 + ply&#93;&#93; &= ~ToMask;
looks *very* suspicious, since TypeBoard is an array of bitboards ...

Do you swear that there will "never ever" be an array bounds overflow?

Edit: ok, I see that I misinterpreted the meaning of "BB", in fact it seems to be a piece type, not a bitboard, despite the name ... But nevertheless, I get the feeling that the whole "TypeBoard" stuff is unintuitive (array index "64 + ply"?). And I would not be surprised if your actual problem were related to some unintuitive code.
yes :) the naming is messed up .

Code: Select all

enum BB &#58;unsigned int &#123; Null = 0, King = 0, Pawn, Knight, Bishop, Rook, Queen, Enemy, Occupied = 14, Empty = 15 &#125;;
enum Color &#123; Black, White = 7 &#125;;
Sven Schüle wrote:Which variables are now members of your class "Position"? Those listed above as "static" (so they are now no longer static)?
yes :

Code: Select all

U64 GameRecord&#91;512&#93;;
	U64 SBackup&#91;MaxDepth&#93;&#91;16&#93;;
	U64 CRBackup&#91;MaxDepth&#93;&#91;2&#93;;
	//use the Game record instead
	U64 PositionKeyBackUp&#91;MaxDepth&#93;;
	U64 HalfMoveClockBackUp&#91;MaxDepth&#93;;

	U64 BitBoards&#91;16&#93;;
	U64 HalfMoveClock = 0ULL;
	U64 GameRecordCounter = 0ULL;
	U64 Positionkey = 0ULL;
	U64 CastleRights&#91;2&#93;;

	unsigned int LastMoveDPushSQBackup&#91;MaxDepth&#93;;
	Score PSQTScoreBackUp&#91;MaxDepth&#93;;

	unsigned int DoublePushSQ&#91;2&#93; = &#123; 0U,0U &#125;;
	Score PSQTScore;


	int ply = 0;
	BB TypeBoard&#91;64 + MaxDepth&#93;;
	Color STM = White;
Henk wrote:10-20% is nothing. You are just wasting your time. (Like I do all day)
they are something , and as I've already pointed in the post this is not my main concern.
Henk wrote:They always told me that object oriented programming is not for free. Calling a virtual method is like dereferencing a pointer to a function. So if you want to code more efficiently use C instead of C++. No nonsense with virtual tables.
to achieve the same functionality they provide you'll have to pay a similar price regardless of the language you are using.