TT in fail-hard alphabeta

Discussion of chess software programming and technical issues.

Moderator: Ras

tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

TT in fail-hard alphabeta

Post by tcusr »

i have a fail-hard alphabeta and so to return the score from the TT i have to do this

Code: Select all

tentry_t *ttable_t::probe(int alpha, int beta, int depth, uint64_t key)
{
	tentry_t *te = &table[key % tt_size];

	if (te->key == key && te->depth >= depth) {
		if (te->bound == lower_bound && te->score >= beta)
			te->score = beta;

		if (te->bound == upper_bound && te->score <= alpha)
			te->score = alpha;

		return te;
	}

	return nullptr;
}
the bound is update like this

Code: Select all

int negamax(alpha, beta, ...)
{
	bound = upper_bound;

	for each move {
		....

		if (score >= beta) {
			tt.store(beta, depth, lower_bound, board.hash());
			return beta;
		}

		if (score > alpha) {
			alpha = score;
			bound = exact_bound;

			pv = std::move(child_pv);
			pv.insert(pv.begin(), move);
		}
	}

	tt.store(alpha, depth, bound, board.hash());
  return alpha;
}
the problem is that with that probing code the pv is cut short at 2 plies and there's no saving of time nor nodes.
the TT starts to work when i do this in probe()

Code: Select all

if ((te->bound == lower_bound && te->score >= beta)
||  (te->bound == upper_bound && te->score <= alpha))
	return te;
but AFAIK this is incorrect because that code is for fail-soft alphabeta.

i also don't see the usual behavior of the TT (with the fail-soft probing) where, after searching to let's say a depth of 8, it doesn't skip directly to 8 when researching the same position again. it's only halving the time it took in the first search. i'm using a TT of 256 mb.

after hash() which generates the board hash key from scratch this is the only code i added so i don't really know what else to do.
any help is appreciated, thanks in advance.
syzygy
Posts: 5695
Joined: Tue Feb 28, 2012 11:56 pm

Re: TT in fail-hard alphabeta

Post by syzygy »

tcusr wrote: Sat May 07, 2022 6:56 pm i have a fail-hard alphabeta and so to return the score from the TT i have to do this
I don't see any need to adjust the score you find in the TT (except for mate scores).

In the search:
If the tt score is an upper bound or exact and <= alpha, then return alpha.
If the tt score is a lower bound or exact and >= beta, then return beta.

There is no reason why you should not do this in the search with fail hard. You should do this if you want to profit from having a TT.
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: TT in fail-hard alphabeta

Post by tcusr »

syzygy wrote: Sat May 07, 2022 9:14 pm
tcusr wrote: Sat May 07, 2022 6:56 pm i have a fail-hard alphabeta and so to return the score from the TT i have to do this
If the tt score is an upper bound or exact and <= alpha, then return alpha.
If the tt score is a lower bound or exact and >= beta, then return beta.
when i get an exact bound i just return it. at least that's what bruce moreland does in his articles unless i'm missing something?
with that one fixed does this behavior look reasonable?
from the start position, TT of 256 mb.

Code: Select all

go depth 9
info depth 1 score cp 28 nps 4000 nodes 4 time 1 pv b1c3
info depth 2 score cp 0 nps 46000 nodes 46 time 1 pv b1c3 b8c6
info depth 3 score cp 28 nps 182000 nodes 182 time 1 pv b1c3 b8c6 g1f3
info depth 4 score cp 0 nps 417250 nodes 1669 time 4 pv b1c3 b8c6 g1f3 g8f6
info depth 5 score cp 18 nps 606000 nodes 7272 time 12 pv b1c3 b8c6 g1f3 g8f6 d2d4
info depth 6 score cp 0 nps 1139684 nodes 64962 time 57 pv b1c3 b8c6 g1f3 g8f6 d2d4 d7d5
info depth 7 score cp 20 nps 1015782 nodes 262072 time 258 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d5 c1e3
info depth 8 score cp 0 nps 1177424 nodes 1828541 time 1553 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d6 c1e3 c8e6
info depth 9 score cp 14 nps 1240164 nodes 22766935 time 18358 pv e2e4 d7d6 b1c3 b8c6 g1f3 g8f6 d2d4 c8e6 c1f4
bestmove e2e4
go depth 9
info depth 1 score cp 28 nps 4000 nodes 4 time 1 pv b1c3
info depth 2 score cp 0 nps 49000 nodes 49 time 1 pv b1c3 b8c6
info depth 3 score cp 28 nps 145000 nodes 145 time 1 pv b1c3 b8c6 g1f3
info depth 4 score cp 13 nps 522333 nodes 1567 time 3 pv e2e4 b8a6 d1h5 g8f6
info depth 5 score cp 18 nps 580250 nodes 4642 time 8 pv b1c3 b8c6 g1f3 g8f6 d2d4
info depth 6 score cp 0 nps 1154023 nodes 49623 time 43 pv b1c3 b8c6 g1f3 g8f6 d2d4 d7d5
info depth 7 score cp 20 nps 1077668 nodes 165961 time 154 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d5 c1e3
info depth 8 score cp 2 nps 1287569 nodes 1248942 time 970 pv b1c3 b8c6 g1f3 g8f6 d2d4 d7d6 d4d5 c6e5
info depth 9 score cp 14 nps 831277 nodes 1373271 time 1652 pv e2e4 d7d6 b1c3 b8c6 g1f3 g8f6 d2d4 c8e6 c1f4
bestmove e2e4
i don't understand why in the second search it doesn't give the score of 14 from the start though.
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: TT in fail-hard alphabeta

Post by tcusr »

tcusr wrote: Sun May 08, 2022 11:53 am i don't understand why in the second search it doesn't give the score of 14 from the start though.
have i been tricked by vice? i've only watched the video about the implementation of the TT and he has that behavior, but only him.

the TT clearly works, it reaches a depth of 40 in Fine 70 easily and i got the same benefits as the others from what i could read in older threads.
but it strangely gives some funny moves sometimes like b1a3 in the start position

Code: Select all

go depth 8
info depth 1 score cp 28 nps 43000 nodes 43 time 1 pv b1c3
info depth 2 score cp 0 nps 192000 nodes 192 time 1 pv b1c3 b8c6
info depth 3 score cp 28 nps 1316000 nodes 1316 time 1 pv b1c3 b8c6 g1f3
info depth 4 score cp 0 nps 2111000 nodes 6333 time 3 pv b1c3 b8c6 g1f3 g8f6
info depth 5 score cp 18 nps 2441642 nodes 34183 time 14 pv b1c3 b8c6 g1f3 g8f6 d2d4
info depth 6 score cp 0 nps 2959000 nodes 204171 time 69 pv b1c3 b8c6 g1f3 g8f6 d2d4 d7d5
info depth 7 score cp 20 nps 3099855 nodes 1007453 time 325 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d5 c1e3
info depth 8 score cp 0 nps 3150690 nodes 5986312 time 1900 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d6 c1e3 c8e6
bestmove b1c3
go depth 8
info depth 1 score cp 8 nps 22000 nodes 22 time 1 pv b1a3
info depth 2 score cp 0 nps 69000 nodes 69 time 1 pv b1c3 b8c6
info depth 3 score cp 8 nps 180000 nodes 180 time 1 pv b1a3 b8c6 g1f3
info depth 4 score cp 0 nps 591000 nodes 591 time 1 pv b1c3 b8c6 g1f3 g8f6
info depth 5 score cp 0 nps 1411000 nodes 2822 time 2 pv b1a3 b8c6 g1f3 g8f6 a3c4
info depth 6 score cp 0 nps 2252428 nodes 15767 time 7 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d6
info depth 7 score cp 0 nps 1828645 nodes 56688 time 31 pv b1a3 b8c6 g1f3 g8f6 a3c4 f6e4 f3e5
info depth 8 score cp 0 nps 2924425 nodes 116977 time 40 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d6 c1e3 c8e6
bestmove b1c3
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: TT in fail-hard alphabeta

Post by tcusr »

tcusr wrote: Sun May 08, 2022 1:25 pm
tcusr wrote: Sun May 08, 2022 11:53 am i don't understand why in the second search it doesn't give the score of 14 from the start though.
the TT clearly works, it reaches a depth of 40 in Fine 70 easily and i got the same benefits as the others from what i could read in older threads.
but it strangely gives some funny moves sometimes like b1a3 in the start position
little update.
it was not Fine 70 where it could reach a depth 40 but another king and pawn endgame, nevertheless in Fine 70 it correctly finds a1b1 after instantaneously reaching depth 30.

i rewrote everything and now no more funny moves and it's a bit faster with a table of only 32 mb. i probably introduced a bug when constantly changing the probing code. i moved all the logic in the search part.

Code: Select all

	tentry_t& te = tt.get_entry(board.hash());
	if (te.key == board.hash() && te.depth >= depth) {
		if (te.bound == exact_bound || te.bound == upper_bound)
			if (te.score <= alpha)
				return alpha;

		if (te.bound == exact_bound || te.bound == lower_bound)
			if (te.score >= beta)
				return beta;
	}
thank you very much syzygy.
syzygy
Posts: 5695
Joined: Tue Feb 28, 2012 11:56 pm

Re: TT in fail-hard alphabeta

Post by syzygy »

tcusr wrote: Sun May 08, 2022 11:53 am
syzygy wrote: Sat May 07, 2022 9:14 pm
tcusr wrote: Sat May 07, 2022 6:56 pm i have a fail-hard alphabeta and so to return the score from the TT i have to do this
If the tt score is an upper bound or exact and <= alpha, then return alpha.
If the tt score is a lower bound or exact and >= beta, then return beta.
when i get an exact bound i just return it. at least that's what bruce moreland does in his articles unless i'm missing something?
with that one fixed does this behavior look reasonable?
If it is exact and between alpha and beta, then you should return the exact value, yes.
If outside (alpha, beta), then fail hard means you return alpha or beta.

(Of course I am assuming that tt->depth >= depth, but you understand that.)
i don't understand why in the second search it doesn't give the score of 14 from the start though.
You seem to have bugs.
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: TT in fail-hard alphabeta

Post by tcusr »

syzygy wrote: Sun May 08, 2022 4:16 pm
tcusr wrote: Sun May 08, 2022 11:53 am
syzygy wrote: Sat May 07, 2022 9:14 pm
tcusr wrote: Sat May 07, 2022 6:56 pm i have a fail-hard alphabeta and so to return the score from the TT i have to do this
If the tt score is an upper bound or exact and <= alpha, then return alpha.
If the tt score is a lower bound or exact and >= beta, then return beta.
when i get an exact bound i just return it. at least that's what bruce moreland does in his articles unless i'm missing something?
with that one fixed does this behavior look reasonable?
If it is exact and between alpha and beta, then you should return the exact value, yes.
If outside (alpha, beta), then fail hard means you return alpha or beta.

(Of course I am assuming that tt->depth >= depth, but you understand that.)
in the posts above i fixed some things and forgot to return the exact score when within alpha and beta bounds. i now added it and it's the fastest version i could get.
the problem is that when i retry searching a position it crashes but i luckily realized it's because i'm accessing elements out of bounds in my std::vector.
i'll find a way to only save the best move so i don't print out an empty pv
i don't understand why in the second search it doesn't give the score of 14 from the start though.
You seem to have bugs.
now it jumps directly to the previous depth with the exact score from depth 1 :D
thank you a lot for your explanations.
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: TT in fail-hard alphabeta

Post by tcusr »

bugs keep coming but at least i know where they're coming from. this time there's the problem of unfinished searches that store the wrong score for the position.
a quick fix would be to clear the hash table between the searches but i don't think it's a good idea, it basically defies the point of having a TT.
what's the general consensus for this?

i'm not too worried though because the programs is now 2x faster and it is able to reach very high depths (as expected) in endgames.
syzygy
Posts: 5695
Joined: Tue Feb 28, 2012 11:56 pm

Re: TT in fail-hard alphabeta

Post by syzygy »

tcusr wrote: Sun May 08, 2022 10:03 pm bugs keep coming but at least i know where they're coming from. this time there's the problem of unfinished searches that store the wrong score for the position.
a quick fix would be to clear the hash table between the searches but i don't think it's a good idea, it basically defies the point of having a TT.
what's the general consensus for this?
If you mean the search was interrupted because time ran out, then make sure you don't store wrong scores in the TT. After recursively calling search(), check whether time is up (by checking a stop flag) and, if so, return immediately.
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: TT in fail-hard alphabeta

Post by tcusr »

syzygy wrote: Sun May 08, 2022 11:02 pm
tcusr wrote: Sun May 08, 2022 10:03 pm bugs keep coming but at least i know where they're coming from. this time there's the problem of unfinished searches that store the wrong score for the position.
a quick fix would be to clear the hash table between the searches but i don't think it's a good idea, it basically defies the point of having a TT.
what's the general consensus for this?
If you mean the search was interrupted because time ran out, then make sure you don't store wrong scores in the TT. After recursively calling search(), check whether time is up (by checking a stop flag) and, if so, return immediately.
i already do that, in my signature you can see the code for my engine.
i solved the problem by not probing at the root.

i probably removed all bugs now (famous last words :) )
PVS + TT cut-offs and hash move + MVV/LVA for ordering

Code: Select all

go depth 9
info depth 1 score cp 28 nps 43000 nodes 43 time 1 pv b1c3
info depth 2 score cp 0 nps 111000 nodes 111 time 1 pv b1c3 b8c6
info depth 3 score cp 28 nps 989000 nodes 989 time 1 pv b1c3 b8c6 g1f3
info depth 4 score cp 0 nps 1823500 nodes 3647 time 2 pv b1c3 b8c6 g1f3 g8f6
info depth 5 score cp 18 nps 2634555 nodes 23711 time 9 pv b1c3 b8c6 g1f3 g8f6 d2d4
info depth 6 score cp 0 nps 2603695 nodes 119770 time 46 pv b1c3 b8c6 g1f3 g8f6 d2d4 d7d5
info depth 7 score cp 20 nps 3040534 nodes 489526 time 161 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d5 c1e3
info depth 8 score cp 0 nps 2734639 nodes 2442033 time 893 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d6 c1e3 c8e6
info depth 9 score cp 14 nps 2645196 nodes 48565812 time 18360 pv e2e4 d7d6 b1c3 b8c6 g1f3 g8f6 d2d4
bestmove e2e4
PVS and MVV/LVA for move ordering

Code: Select all

go depth 9
info depth 1 score cp 28 nps 4000 nodes 4 time 1 pv b1c3
info depth 2 score cp 0 nps 43000 nodes 43 time 1 pv b1c3 b8c6
info depth 3 score cp 28 nps 97000 nodes 97 time 1 pv b1c3 b8c6 g1f3
info depth 4 score cp 0 nps 502666 nodes 1508 time 3 pv b1c3 b8c6 g1f3 g8f6
info depth 5 score cp 18 nps 632636 nodes 6959 time 11 pv b1c3 b8c6 g1f3 g8f6 d2d4
info depth 6 score cp 0 nps 1354608 nodes 93468 time 69 pv b1c3 b8c6 g1f3 g8f6 d2d4 d7d5
info depth 7 score cp 20 nps 1031005 nodes 397968 time 386 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d5 c1e3
info depth 8 score cp 0 nps 1306868 nodes 3920604 time 3000 pv b1c3 b8c6 g1f3 g8f6 d2d3 d7d6 c1e3 c8e6
info depth 9 score cp 14 nps 1244713 nodes 72579253 time 58310 pv e2e4 d7d6 b1c3 b8c6 g1f3 g8f6 d2d4 c8e6 c1f4
bestmove e2e4