Page 1 of 1

kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 8:08 pm
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

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 8:10 pm
by Dann Corbit
The burning question here is why did the named pipe stuff fail.

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 8:20 pm
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

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 8:36 pm
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

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 8:45 pm
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.

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 8:55 pm
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

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 9:04 pm
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.

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 9:13 pm
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

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 9:59 pm
by Spock
Posting in the programming sub-section may have got more responses

Re: kbhit() taking huge CPU??

Posted: Wed Apr 01, 2009 10:05 pm
by JVMerlino
See, I told you it would be a stupid solution. :-)

Thanks, Ray!