Searching using slow eval with tactical verification

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

thomasahle
Posts: 94
Joined: Thu Feb 27, 2014 8:19 pm

Re: Searching using slow eval with tactical verification

Post by thomasahle »

matthewlai wrote:
mcostalba wrote:
matthewlai wrote: Then you can cut it off at any point where all the remaining smaller terms can't add up to be larger than any of the bigger terms.

But I can't do that because I have no idea how my eval() works. It's just a bunch of matrices.
Can't you still evaluate the terms in order of largest weights? I wonder if the weights in your matrices are mostly uniform, or some are much larger than others?
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: Searching using slow eval with tactical verification

Post by matthewlai »

thomasahle wrote: Can't you still evaluate the terms in order of largest weights? I wonder if the weights in your matrices are mostly uniform, or some are much larger than others?
It would be possible if the network has no hidden layers. With 2 hidden layers it's impossible to do something like this.

Also, when evaluating full matrices I can use the CPU's SIMD instructions, which are many times faster than scalar instructions. If I had to evaluate more than 10% or so of the weights, it would be more efficient to just evaluate the whole thing.

Also, matrix-vector multiplications are usually bound by memory bandwidth (as opposed to matrix-matrix multiplications, which are usually bound by CPU), and since weights are loaded in cache line units, evaluating some of the weights may require loading most of the matrices anyways.
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
Sergei S. Markoff
Posts: 227
Joined: Mon Sep 12, 2011 11:27 pm
Location: Moscow, Russia

Re: Searching using slow eval with tactical verification

Post by Sergei S. Markoff »

SmarThink eval function is very slow so I've implemented an original lazy eval approach.

Code: Select all

int LazyEval(void)
{
	int material = thread_board.Material[thread_board.SideToMove] - thread_board.Material[ChangeSide(thread_board.SideToMove)];
	int min_lazy, max_lazy;

	if (CurSide == thread_board.SideToMove)
	{
		min_lazy = root.min_material_lazy;
		max_lazy = root.max_material_lazy;
	}
	else
	{
		min_lazy = -root.max_material_lazy;
		max_lazy = -root.min_material_lazy;
	}

	if &#40;material < min_lazy&#41;
	&#123;
		if (&#40;thread_board.PieceCount&#91;PAWN&#93;&#91;ChangeSide&#40;thread_board.SideToMove&#41;&#93; > 1 || thread_board.NumOfPieces&#91;ChangeSide&#40;thread_board.SideToMove&#41;&#93; > 9&#41; && &#40;thread_board.NumOfPieces&#91;ChangeSide&#40;thread_board.SideToMove&#41;&#93; > 5&#41;)
		&#123;
			if &#40;thread_board.SideToMove&#41;
			&#123;
				if &#40;black_pawns_bb & FULLROW&#40;1&#41;) material += 100;
				else if &#40;black_pawns_bb & FULLROW&#40;2&#41;) material += 50;
			&#125;
			else
			&#123;
				if &#40;white_pawns_bb & FULLROW&#40;6&#41;) material += 100;
				else if &#40;white_pawns_bb & FULLROW&#40;5&#41;) material += 50;
			&#125;

			if &#40;material < min_lazy&#41; return material;
		&#125;
	&#125;
	else if &#40;material > max_lazy&#41;
	&#123;
		if (&#40;thread_board.PieceCount&#91;PAWN&#93;&#91;thread_board.SideToMove&#93; > 1 || thread_board.NumOfPieces&#91;thread_board.SideToMove&#93; > 9&#41; && &#40;thread_board.NumOfPieces&#91;thread_board.SideToMove&#93; > 5&#41;)
		&#123;
			if &#40;thread_board.SideToMove&#41;
			&#123;
				if &#40;white_pawns_bb & FULLROW&#40;6&#41;) material -= 100;
				else if &#40;white_pawns_bb & FULLROW&#40;5&#41;) material -= 50;
			&#125;
			else
			&#123;
				if &#40;black_pawns_bb & FULLROW&#40;1&#41;) material -= 100;
				else if &#40;black_pawns_bb & FULLROW&#40;2&#41;) material -= 50;
			&#125;

			if &#40;material > max_lazy&#41; return material;
		&#125;
	&#125;

	return INFINITY;
&#125;
And at any next IID iteration I'm going to update this "lazy window":

Code: Select all

void RecalcLazyBounds&#40;int root_depth&#41;
&#123;
	root.root_material = thread_board.Material&#91;CurSide&#93; - thread_board.Material&#91;ChangeSide&#40;CurSide&#41;&#93;;
	root.min_material_lazy = MIN&#40;root_move_eval&#91;0&#93;, root.root_material&#41; - 200 - root_depth * 5 + MIN&#40;150, MAX&#40;-150, root_move_eval&#91;0&#93; / 5&#41;);
	root.max_material_lazy = MAX&#40;root_move_eval&#91;0&#93;, root.root_material&#41; + 200 + root_depth * 5 + MIN&#40;150, MAX&#40;-150, root_move_eval&#91;0&#93; / 5&#41;);
&#125;
So if the root eval is 0 at any iteration I will have window [-200;200] for depth 0, [-205;205] at depth 1, [-250;250] at root depth 10 and so on. All evaluation outside this window will be replaced with only material eval. Surprisingly it works for me. If you're interested you can try it)
I will be glad for any feedback)
The Force Be With You!