kbhit() taking huge CPU??

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

Moderators: hgm, Harvey Williamson, bob

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
Post Reply
User avatar
JVMerlino
Posts: 999
Joined: Wed Mar 08, 2006 9:15 pm
Location: San Francisco, California

kbhit() taking huge CPU??

Post by JVMerlino » Wed Apr 01, 2009 6:08 pm

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: 9847
Joined: Wed Mar 08, 2006 7:57 pm
Location: Redmond, WA USA
Contact:

Re: kbhit() taking huge CPU??

Post by Dann Corbit » Wed Apr 01, 2009 6:10 pm

The burning question here is why did the named pipe stuff fail.

User avatar
JVMerlino
Posts: 999
Joined: Wed Mar 08, 2006 9:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino » Wed Apr 01, 2009 6:20 pm

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: 6386
Joined: Thu Mar 09, 2006 7:30 pm
Location: Chicago, Illinois, USA
Contact:

Re: kbhit() taking huge CPU??

Post by michiguel » Wed Apr 01, 2009 6:36 pm

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: 1327
Joined: Fri Jul 14, 2006 5:56 am
Location: London, England
Contact:

Re: kbhit() taking huge CPU??

Post by Jim Ablett » Wed Apr 01, 2009 6:45 pm

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.

User avatar
JVMerlino
Posts: 999
Joined: Wed Mar 08, 2006 9:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino » Wed Apr 01, 2009 6:55 pm

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: 1327
Joined: Fri Jul 14, 2006 5:56 am
Location: London, England
Contact:

Re: kbhit() taking huge CPU??

Post by Jim Ablett » Wed Apr 01, 2009 7:04 pm

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.

User avatar
JVMerlino
Posts: 999
Joined: Wed Mar 08, 2006 9:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino » Wed Apr 01, 2009 7:13 pm

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 » Wed Apr 01, 2009 7:59 pm

Posting in the programming sub-section may have got more responses

User avatar
JVMerlino
Posts: 999
Joined: Wed Mar 08, 2006 9:15 pm
Location: San Francisco, California

Re: kbhit() taking huge CPU??

Post by JVMerlino » Wed Apr 01, 2009 8:05 pm

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

Thanks, Ray!

Post Reply