kbhit() taking huge CPU??

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Rebel, chrisw

JVMerlino
Posts: 1357
Joined: Wed Mar 08, 2006 10:15 pm
Location: San Francisco, California

kbhit() taking huge CPU??

Post by JVMerlino »

It figures this would happen around April 1st.

Still working on Myrddin, I was perplexed by how much slower the engine appeared to be in console mode compared to being run inside a GUI.

After spending quite a bit of time with various MSVC compiler options, Task Manager, and Intel's VTUNE (which I highly recommend, by the way), I have discovered that it is the call to kbhit() that is taking an average of 30% of the CPU, as sometimes as much as 50%.

Task Manager shows the program CSRSS.EXE as hogging the CPU.

VTUNE shows kbhit() calling the Windows Kernel function GetNumberOfConsoleInputEvents(), which then calls the NTDLL function CsrClientCallServer() function. It is this last function that appears to be the culprit.

Here's all of the relevant code:

Code: Select all

/*========================================================================
** InitializeInput -- Open the stdin pipe for reading
**========================================================================
*/
void InitializeInput(void)
{
	DWORD	dw;

	input_handle = GetStdHandle(STD_INPUT_HANDLE);
	is_pipe = !GetConsoleMode(input_handle, &dw);

	setbuf(stdout, NULL);
}

/*========================================================================
** IsInputAvailable -- Check the stdin pipe for input
**========================================================================
*/
int IsInputAvailable(void)
{
	DWORD	nchars;

	if (stdin->_cnt > 0)
		return 1;

	if (is_pipe)
	{
		if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL))
			return 1;

		return (nchars);
	}
	else
		return(_kbhit());
}

/*========================================================================
** CheckForInput - Check for user input
**========================================================================
*/
BOOL	CheckForInput(BOOL bWaitForInput)
{
	if (bWaitForInput == FALSE)
	{
		if (!IsInputAvailable())
			return(FALSE);
	}

	if (!fgets(line, 256, stdin))
		return(-1);	// shouldn't ever happen

	if (line[0] == '\n')
		return(FALSE);

#if LOGFILE
	fprintf(logfile, "> Received %s", line);
#endif
	sscanf(line, "%s", command);

	return(TRUE);
}
Most engine programmers will recognize this as very similar to the code from Crafty (which I also found with slight variations in many other engines).

I call CheckForInput() about once every 8K nodes. Changing how often I call it does not seem to have an appreciable effect (which is also very bizarre). Running Myrddin from inside the compiler (for both the release and the debug versions) is no different from running it manually from Windows.

I've compiled Crafty with the same settings, and Greko as well. Neither of the resulting programs show the same behavior as with Myrddin. As a last result, I have even copied the equivalent code from Crafty, with the same poor results.

Clearly, I'm missing something, which I hope that somebody out there has had to deal with before. Any recommendations would be most welcome. This is not how I expected to spend my time working on Alpha 2. :P

jm
Dann Corbit
Posts: 12537
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: kbhit() taking huge CPU??

Post by Dann Corbit »

The burning question here is why did the named pipe stuff fail.
JVMerlino
Posts: 1357
Joined: Wed Mar 08, 2006 10:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino »

Really? I'm under the impression that GetConsoleMode() will return TRUE if the app is being run in a console window, and therefore is_pipe will be FALSE.

But, when running Myrddin under a GUI (I've tried Winboard, Arena and Chessmaster), is_pipe will be TRUE, bypassing the call to kbhit() and allowing full CPU usage.

jm
User avatar
michiguel
Posts: 6401
Joined: Thu Mar 09, 2006 8:30 pm
Location: Chicago, Illinois, USA

Re: kbhit() taking huge CPU??

Post by michiguel »

JVMerlino wrote:It figures this would happen around April 1st.

Still working on Myrddin, I was perplexed by how much slower the engine appeared to be in console mode compared to being run inside a GUI.

After spending quite a bit of time with various MSVC compiler options, Task Manager, and Intel's VTUNE (which I highly recommend, by the way), I have discovered that it is the call to kbhit() that is taking an average of 30% of the CPU, as sometimes as much as 50%.

Task Manager shows the program CSRSS.EXE as hogging the CPU.

VTUNE shows kbhit() calling the Windows Kernel function GetNumberOfConsoleInputEvents(), which then calls the NTDLL function CsrClientCallServer() function. It is this last function that appears to be the culprit.

Here's all of the relevant code:

Code: Select all

/*========================================================================
** InitializeInput -- Open the stdin pipe for reading
**========================================================================
*/
void InitializeInput(void)
{
	DWORD	dw;

	input_handle = GetStdHandle(STD_INPUT_HANDLE);
	is_pipe = !GetConsoleMode(input_handle, &dw);

	setbuf(stdout, NULL);
}

/*========================================================================
** IsInputAvailable -- Check the stdin pipe for input
**========================================================================
*/
int IsInputAvailable(void)
{
	DWORD	nchars;

	if (stdin->_cnt > 0)
		return 1;

	if (is_pipe)
	{
		if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL))
			return 1;

		return (nchars);
	}
	else
		return(_kbhit());
}

/*========================================================================
** CheckForInput - Check for user input
**========================================================================
*/
BOOL	CheckForInput(BOOL bWaitForInput)
{
	if (bWaitForInput == FALSE)
	{
		if (!IsInputAvailable())
			return(FALSE);
	}

	if (!fgets(line, 256, stdin))
		return(-1);	// shouldn't ever happen

	if (line[0] == '\n')
		return(FALSE);

#if LOGFILE
	fprintf(logfile, "> Received %s", line);
#endif
	sscanf(line, "%s", command);

	return(TRUE);
}
Most engine programmers will recognize this as very similar to the code from Crafty (which I also found with slight variations in many other engines).

I call CheckForInput() about once every 8K nodes. Changing how often I call it does not seem to have an appreciable effect (which is also very bizarre). Running Myrddin from inside the compiler (for both the release and the debug versions) is no different from running it manually from Windows.

I've compiled Crafty with the same settings, and Greko as well. Neither of the resulting programs show the same behavior as with Myrddin. As a last result, I have even copied the equivalent code from Crafty, with the same poor results.

Clearly, I'm missing something, which I hope that somebody out there has had to deal with before. Any recommendations would be most welcome. This is not how I expected to spend my time working on Alpha 2. :P

jm
I have no idea, but I would like to recommend you to use two threads, one for searching, and another for the command interface. It is much easier to deal with all this stuff.

Miguel
User avatar
Jim Ablett
Posts: 1383
Joined: Fri Jul 14, 2006 7:56 am
Location: London, England
Full name: Jim Ablett

Re: kbhit() taking huge CPU??

Post by Jim Ablett »

Hi John,

I take it your Windows programmimg so what's with using the 'kbhit()' ?
That's a Posix function.

This is Windows Bioskey() from Olithink >

Code: Select all

 static int init = 0, pipe;
   static HANDLE inh;
   DWORD dw;

   if (!init) {
     init = 1;
     inh = GetStdHandle(STD_INPUT_HANDLE);
     pipe = !GetConsoleMode(inh, &dw);
     if (!pipe) {
        SetConsoleMode(inh, dw & ~(ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT));
        FlushConsoleInputBuffer(inh);
      }
    }
    if (pipe) {
      if (!PeekNamedPipe(inh, NULL, 0, NULL, &dw, NULL)) return 1;
      return dw;
    } else {
      GetNumberOfConsoleInputEvents(inh, &dw);
      return dw <= 1 ? 0 &#58; dw;
    &#125;
Jim.
JVMerlino
Posts: 1357
Joined: Wed Mar 08, 2006 10:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino »

Jim Ablett wrote:Hi John,

I take it your Windows programmimg so what's with using the 'kbhit()' ?
That's a Posix function.

This is Windows Bioskey() from Olithink >

Code: Select all

 static int init = 0, pipe;
   static HANDLE inh;
   DWORD dw;

   if (!init&#41; &#123;
     init = 1;
     inh = GetStdHandle&#40;STD_INPUT_HANDLE&#41;;
     pipe = !GetConsoleMode&#40;inh, &dw&#41;;
     if (!pipe&#41; &#123;
        SetConsoleMode&#40;inh, dw & ~&#40;ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT&#41;);
        FlushConsoleInputBuffer&#40;inh&#41;;
      &#125;
    &#125;
    if &#40;pipe&#41; &#123;
      if (!PeekNamedPipe&#40;inh, NULL, 0, NULL, &dw, NULL&#41;) return 1;
      return dw;
    &#125; else &#123;
      GetNumberOfConsoleInputEvents&#40;inh, &dw&#41;;
      return dw <= 1 ? 0 &#58; dw;
    &#125;
Jim.
That's pretty much the same code as in Crafty. I've tried it, with no improvement.

jm
User avatar
Jim Ablett
Posts: 1383
Joined: Fri Jul 14, 2006 7:56 am
Location: London, England
Full name: Jim Ablett

Re: kbhit() taking huge CPU??

Post by Jim Ablett »

I take it your Windows programmimg so what's with using the 'kbhit()' ?
That's a Posix function.
I stand corrected. It's included in Visual C++ using conio.h header. > http://msdn.microsoft.com/en-us/library ... 80%29.aspx

Jim.
JVMerlino
Posts: 1357
Joined: Wed Mar 08, 2006 10:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino »

Jim Ablett wrote:
I take it your Windows programmimg so what's with using the 'kbhit()' ?
That's a Posix function.
I stand corrected. It's included in Visual C++ using conio.h header. > http://msdn.microsoft.com/en-us/library ... 80%29.aspx

Jim.
No worries, but my god this is frustrating. I wonder how stupid the solution is going to be?

jm
Spock

Re: kbhit() taking huge CPU??

Post by Spock »

Posting in the programming sub-section may have got more responses
JVMerlino
Posts: 1357
Joined: Wed Mar 08, 2006 10:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino »

See, I told you it would be a stupid solution. :-)

Thanks, Ray!