I get a performance hit when I count that way, simply because that leads to higher number of times the node count is incremented. Here's why: If you count at the top of search/qsearch, it ignores hash hits (so your nps goes down in high hashing positions). But if you count after a legal MakeMove(), it counts all legal moves made to the board, whether or not there will be a hash hit (so your nps goes up with high hash hits). In one of my test puzzles, the former method yielded 20 million nodes, while the latter method yielded 120 millions nodes (it was a high hash hit position, King Rook vs King, no egtb) and took a lot longer, because it executed the increment line 100 million more times. I think the difference was something like 142 seconds (former) vs. 160 seconds (latter)... Although my node count variable is an unsigned 64 bit integer, which perhaps is inefficient, perhaps I should use an unsigned 32 bit int instead...sje wrote:If you have a legal move only generator:If you don't:Code: Select all
ExecuteMove(); node_count++;
Code: Select all
ExecuteMove(); if (LegalPosition()) node_count++;
definition of a node
Moderator: Ras
Re: My definition of a node
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: My definition of a node
How is that the case?AndrewShort wrote:I get a performance hit when I count that way, simply because that leads to higher number of times the node count is incremented. Here's why: If you count at the top of search/qsearch, it ignores hash hits (so your nps goes down in high hashing positions). But if you count after a legal MakeMove(), it counts all legal moves made to the board, whether or not there will be a hash hit (so your nps goes up with high hash hits). In one of my test puzzles, the former method yielded 20 million nodes, while the latter method yielded 120 millions nodes (it was a high hash hit position, King Rook vs King, no egtb) and took a lot longer, because it executed the increment line 100 million more times. I think the difference was something like 142 seconds (former) vs. 160 seconds (latter)... Although my node count variable is an unsigned 64 bit integer, which perhaps is inefficient, perhaps I should use an unsigned 32 bit int instead...sje wrote:If you have a legal move only generator:If you don't:Code: Select all
ExecuteMove(); node_count++;
Code: Select all
ExecuteMove(); if (LegalPosition()) node_count++;
My search looks like this:
Search() {
nodes_searched++;
repetition / 50 move check
hash probe
egtb probe
null-move search
while (n=NextMove()) {
Make
call search/quiesce
Unmake
}
}
You guys are coming up with some bizarre implementations of a normal negamax search.

I don't see how the mentioned change would change NPS enough to measure. Most positions are perfectly legal anyway unless you start off in a wild tactical position with a forced mate... And if you generate legal moves to escape check, the number of illegal moves is very small, and whether you count them or not is just "noise" to the overall number... Nobody cares whether you search 100,234,567 nodes on an N-ply search for position P or you only searched 100,000,000 nodes. Most care about the 100M vs 600M type differences, and this is not going to come anywhere near that kind of error margin.
Re: My definition of a node
my search doesn't look like that, simply because I need to go back and clean it up. As I've added features, it's gotten a little messy. This thread and your responses have inspired me to clean it up, so thanks. I'm sure I'll get at least a 4% gain as someone else reported...
-
- Posts: 4675
- Joined: Mon Mar 13, 2006 7:43 pm
Re: My definition of a node
Change:bob wrote: My search looks like this:
Search() {
nodes_searched++;
repetition / 50 move check
hash probe
egtb probe
null-move search
while (n=NextMove()) {
Make
call search/quiesce
Unmake
}
}
repetition / 50 move check
To:
repetition / 50 move check / insufficient mating material check
I agree with Bob; simply incrementing a 64 bit counter should have next to no effect on timing statistics. Well, unless you happen to be using an 8 bit machine.
To get a good idea of the actual cost of incrementing the node count, try running two versions with one version having the incrementation commented out.
-
- Posts: 28356
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: My definition of a node
Not even then: only once every 256 times you have to touch anything but the lowest 8 bits.sje wrote: Well, unless you happen to be using an 8 bit machine.
Re: My definition of a node
In my present screwy way of doing search, the difference between counting nodes and not counting nodes is usually unnoticeable. My point was that for positions where you get high number of hash hits, the difference can be quite noticeable, if you measure the difference between including hash hits as nodes or not, since in my particular example, it means executing an increment (VB: nodes=nodes+1) literally 100 million more times than otherwise.
Isn't it true that running a VB statement nodes=nodes+1 100 million times is not free? In my case if I count differently (simply move where I count, which effectively counts less), it saved something like 20 seconds in time...
Isn't it true that running a VB statement nodes=nodes+1 100 million times is not free? In my case if I count differently (simply move where I count, which effectively counts less), it saved something like 20 seconds in time...
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: My definition of a node
If that is all you do, it would have a cost. But with modern super-scalar out-of-order execution CPUs, those instructions get interlaced with other instructions and the cost very well might be zero or very close to it...AndrewShort wrote:In my present screwy way of doing search, the difference between counting nodes and not counting nodes is usually unnoticeable. My point was that for positions where you get high number of hash hits, the difference can be quite noticeable, if you measure the difference between including hash hits as nodes or not, since in my particular example, it means executing an increment (VB: nodes=nodes+1) literally 100 million more times than otherwise.
Isn't it true that running a VB statement nodes=nodes+1 100 million times is not free? In my case if I count differently (simply move where I count, which effectively counts less), it saved something like 20 seconds in time...
Re: My definition of a node
not in front of my pc now, but I think I'm incrementing like this:
ulNodes = CULng(ulNodes + 1)
That might be my problem... I think vb complains without the casting ...,but if I let it cast implicitly it might be faster? I'll have to try..as you can tell I'm not a "real" dev type..
ulNodes = CULng(ulNodes + 1)
That might be my problem... I think vb complains without the casting ...,but if I let it cast implicitly it might be faster? I'll have to try..as you can tell I'm not a "real" dev type..

-
- Posts: 4675
- Joined: Mon Mar 13, 2006 7:43 pm
Re: My definition of a node
First, some of us don't use any Microsoft development tools at all, let alone Visual Basic. So it's quite possible that VB is inserting some kind of extra run time code for conversion, overflow checking, or exception processing and nobody here can help.
The best way to determine incremental execution cost is to write a pair of simple timing loops; one with a 64 bit increment and one with TWO 64 bit increments of separate variables. Run both and do a little linear algebra and you'll get exact numbers.
The best way to determine incremental execution cost is to write a pair of simple timing loops; one with a 64 bit increment and one with TWO 64 bit increments of separate variables. Run both and do a little linear algebra and you'll get exact numbers.