nps command

Discussions about the WinBoard protocol. Here you can also report bugs and request new features.

Moderators: hgm, Andres Valverde

nps command

Postby Miguel A. Ballicora » 18 Oct 2009, 08:43

I am trying to implement nps but I am a bit confused. The protocol says

nps NODE_RATE
The engine should not use wall-clock time to make its timing decisions, but an own internal time measure based on the number of nodes it has searched (and will report as "thinking output", see section 10), converted to seconds through dividing by the given NODE_RATE. Example: after receiving the commands "st 8" and "nps 10000", the engine should never use more that 80,000 nodes in the search for any move. In this mode, the engine should report user CPU time used (in its thinking output), rather than wall-clock time. This even holds if NODE_RATE is given as 0, but in that case it should also use the user CPU time for its timing decisions. The effect of an "nps" command should persist until the next "new" command.

Red: What does exactly mean user CPU time used?

is in this case "user CPU time used" == (nodes_used / NODE_RATE) ?

Blue: What is the actual spirit and meaning of nps 0? disabling it? If the previous case is correct, the "user CPU time used" is infinite.

Miguel
User avatar
Miguel A. Ballicora
 
Posts: 160
Joined: 03 Aug 2005, 02:24
Location: Chicago, IL, USA

Re: nps command

Postby H.G.Muller » 18 Oct 2009, 19:33

Normally engines take their timing decisions based on wall-clock time, as can be for instance obtained through a call like GetTimeOfDay() or (in Windows) GetTickCount(). The idea of nps 0 is that you would replace that by a call to a function like clock(), which measures only the time that the engine is using the CPU, but stops ticking when the engine process is stalled because it is waiting to be swapped into memory, or waiting because another process on the same computer is using the CPU. In this mode the engine should report this time in the time field of its Thinking Output, and the GUI will use this time reported by the engine to decrement the engine's clock, rather than its own time measurement.

So in an engine that containes a routine GetTime() to read the clock, to implement the nps command in it, you would have to change that routine to:
Code: Select all
int GetTime()
{
    if(nodeRate < 0) return GetTickCount(); // msec
    if(nodeRate == 0) return clock()*(1000./CLOCKS_PER_SEC);
    return nodeCount*(1000./nps);
}

Of course an efficient implementation would avoid actual division, by precomputing a reciprocal. E.g. factor = (1000<<20)/nps; and then use (nodeCount*factor) >> 20.
User avatar
H.G.Muller
 
Posts: 3453
Joined: 16 Nov 2005, 12:02
Location: Diemen, NL

Re: nps command

Postby Miguel A. Ballicora » 18 Oct 2009, 21:12

H.G.Muller wrote:Normally engines take their timing decisions based on wall-clock time, as can be for instance obtained through a call like GetTimeOfDay() or (in Windows) GetTickCount(). The idea of nps 0 is that you would replace that by a call to a function like clock(), which measures only the time that the engine is using the CPU, but stops ticking when the engine process is stalled because it is waiting to be swapped into memory, or waiting because another process on the same computer is using the CPU. In this mode the engine should report this time in the time field of its Thinking Output, and the GUI will use this time reported by the engine to decrement the engine's clock, rather than its own time measurement.

So in an engine that containes a routine GetTime() to read the clock, to implement the nps command in it, you would have to change that routine to:
Code: Select all
int GetTime()
{
    if(nodeRate < 0) return GetTickCount(); // msec
    if(nodeRate == 0) return clock()*(1000./CLOCKS_PER_SEC);
    return nodeCount*(1000./nps);
}

Of course an efficient implementation would avoid actual division, by precomputing a reciprocal. E.g. factor = (1000<<20)/nps; and then use (nodeCount*factor) >> 20.


Ok, from your post I now understand that

1) negative nodeRate is used to disable this feature to use the traditional Wall time. I think this should be spelled out in the protocol. As I read the protocol, it looks like negative numbers are undefined. In fact, my current implementation attempt has is as an unsigned int :-) I will change it.

2) nodeRate == 0 the engine measure its own CPU time, regardless of the node counts. Is this really needed? How is it going to be used? The problem is that clock() can give serious problems for SMP engines. It may be needed to divide by the number of CPUS used. With two threads used, clock() could be up to twice as big as wall time. However, this is not portable and I think the standards say nothing about it. I am not an expert on this specific issue, but I think it will be a pain in the butt to maintain this portable. This may vary from compiler to compiler besides variations from OS to OS. Another problem with clock() is that the resolution could be really coarse.

3) positive numbers is the heart of the feature, to use the actual nodes as "clock".

What is the default value for nodeRate when the engine starts? I assume it should be any negative number?

The protocol says that I should keep this value until the next "new". But...
What value should I set it when I receive the next "new"? Should I leave the previous value untouched or should I reset it to the default value? or is it undefined?

Miguel
PS: I do not think that a division is a big problem. This code is not executed in every single node.
User avatar
Miguel A. Ballicora
 
Posts: 160
Joined: 03 Aug 2005, 02:24
Location: Chicago, IL, USA

Re: nps command

Postby H.G.Muller » 19 Oct 2009, 08:42

The negative rates are not really a part of the protocol: WinBoard never sends nps R with R<0. But it would be a straightforward implementation to use an invalid value for the node rate when the feature should not be used. WinBoard does this internally to indicate usual play by wall-clock time (just like an timeIncrement < 0 iternally indicates it should apply classical TC). In that case it does not send an nps command to the engine at all.

The new command should switch back to the default, i.e. play per wall-clock time. Current protocol specs contain no command to switch off the feature during a game. In the engine the processing of the new command that belongs to the GetTime code I presented above would be

Code: Select all
maxDepth = INF; // undo any prior sd command
maxTime = INF; // undo any prior st command
nodeRate = -1; // undo any prior nps command
User avatar
H.G.Muller
 
Posts: 3453
Joined: 16 Nov 2005, 12:02
Location: Diemen, NL

Re: nps command

Postby Miguel A. Ballicora » 19 Oct 2009, 21:26

H.G.Muller wrote:The negative rates are not really a part of the protocol: WinBoard never sends nps R with R<0. But it would be a straightforward implementation to use an invalid value for the node rate when the feature should not be used. WinBoard does this internally to indicate usual play by wall-clock time (just like an timeIncrement < 0 iternally indicates it should apply classical TC). In that case it does not send an nps command to the engine at all.

The new command should switch back to the default, i.e. play per wall-clock time. Current protocol specs contain no command to switch off the feature during a game. In the engine the processing of the new command that belongs to the GetTime code I presented above would be

Code: Select all
maxDepth = INF; // undo any prior sd command
maxTime = INF; // undo any prior st command
nodeRate = -1; // undo any prior nps command


Thanks, I think I am sure now what I have to do. Anyway, I still think that you should expand the document with a brief summary of what you wrote here.

One more philosophical issue. You say:
"The negative rates are not really a part of the protocol: WinBoard never sends nps R with R<0. But it would be a straightforward implementation to use an invalid value for the node rate when the feature should not be used."

If it is not part of the protocol, the value is undefined behavior and should never be used. If the value could be used by other GUI, then it is part of the protocol. This should be spelled out and include it before people start implementing this in many creative (wrong) ways.

Miguel
User avatar
Miguel A. Ballicora
 
Posts: 160
Joined: 03 Aug 2005, 02:24
Location: Chicago, IL, USA

Re: nps command

Postby H.G.Muller » 19 Oct 2009, 23:22

What I meant to say is that if it is undefined in the protocol, the implementation in the engine could use these values for any purpose it likes. Like indicating it should use wall-clock time.
User avatar
H.G.Muller
 
Posts: 3453
Joined: 16 Nov 2005, 12:02
Location: Diemen, NL


Return to WinBoard development and bugfixing

Who is online

Users browsing this forum: No registered users and 21 guests