Engines lose time (not only) under ChessGUI.

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

Moderators: hgm, Rebel, chrisw

User avatar
Matthias Gemuh
Posts: 3245
Joined: Thu Mar 09, 2006 9:10 am

Re: Engines lose time (not only) under ChessGUI.

Post by Matthias Gemuh »

hgm wrote:What you say is either not correct,or you are using confusing terminology.

WriteFile has _no_ buffer associated with it.
If you are right, then I definitely misunderstood this quote from documentation:
"Typically the WriteFile and WriteFileEx functions write data to an internal buffer that the operating system writes to a disk or communication pipe on a regular basis. "

Matthias.
My engine was quite strong till I added knowledge to it.
http://www.chess.hylogic.de
User avatar
Matthias Gemuh
Posts: 3245
Joined: Thu Mar 09, 2006 9:10 am

Re: Engines lose time (not only) under ChessGUI.

Post by Matthias Gemuh »

Matthias Gemuh wrote:
hgm wrote:What you say is either not correct,or you are using confusing terminology.

WriteFile has _no_ buffer associated with it.
If you are right, then I definitely misunderstood this quote from documentation:
"Typically the WriteFile and WriteFileEx functions write data to an internal buffer that the operating system writes to a disk or communication pipe on a regular basis. "

Matthias.
Doesn't that sound like there is an internal buffer somewhere into which WriteFile() writes, and data from that internal buffer is only transported on a regular basis into the pipe ?
My engine was quite strong till I added knowledge to it.
http://www.chess.hylogic.de
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Engines lose time (not only) under ChessGUI.

Post by hgm »

Where do you quote this from? I cannot find anything lke this in the WriteFile docs I have at http://msdn.microsoft.com/en-us/library ... S.85).aspx .

I can only make sense of what you quote when 'internal' here means internal to the operating system. Meaning the user has no control whatsoever over the flushing of it. The OS has to buffer ('cache') data that has to be written to disk, to wait for the desired sector to pass underneath the write head. and there is no way this could be speeded up.

Reading through the docs I must admit that they are a bit confusing. In normal operation, there are several levels of buffering / caching involved:

1) A user uses a high-level output routine like fprintf() to write to a file. This library routine usually buffers a few KB, because invoking the OS is relatively expensive, and users typically use printf for strings of 10-100 bytes only. So it accumulates them. This is what we normally refer to as 'buffered I/O', and this is what we want to switch off in engine <-> GUI communication, because we expect immediate reply to our fprintf-ed messages, which will not come if they are not actually sent. If it is done, the user has to explicitly flush buffers before starting to ait for an answer. WriteFile() is a low-levelI/O routine, that never does this kind of buffering.
In fact, calling fflush() to flush the fprintf() buffer will use WriteFile() to flush the buffer.

2) There is buffering ('caching') by the OS. Normally, a WriteFile() or fflush() by the user wouldlead the system to copy the user data to a system buffer, so that the WriteFile can return immediately, even though the physical writing might take time to complete. This caching is normally fully transparent to the user. Even when reading the file back before the data is physically written to disk, the OS will substitute the buffer contents, and hand that to the reader. There is no way a user can flush such buffers. But there is an I/O mode that MicroSoft calls 'Ubuffered File I/O'. Basically this does not mean such buffering no longer takes place, but it means that the copying to the OS buffer is skipped, and that the original data in the application memory space is used as the buffer. When the time has arrived that it is physically possible to write the data, the OS now takes it directly from the user buffer. This form of I/O is very tricky, subject to all kind of alignment and size resrtictions on the user data (because it must match the format of the buffers normally used by the OS.

I don't think the latter unbuffered mode makes any sense on pipes. (It might not even exist there.)
User avatar
Matthias Gemuh
Posts: 3245
Joined: Thu Mar 09, 2006 9:10 am

Re: Engines lose time (not only) under ChessGUI.

Post by Matthias Gemuh »

Sorry, HGM.

I got fed up with ChessGUI and forgot about our discussion.
I quoted the internal buffer stuff from here:

http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Flushing that one is blocking.
Not flushing it means the OS will flush when it deems most efficient.

Matthias.
My engine was quite strong till I added knowledge to it.
http://www.chess.hylogic.de
User avatar
Matthias Gemuh
Posts: 3245
Joined: Thu Mar 09, 2006 9:10 am

Re: Engines lose time (not only) under ChessGUI.

Post by Matthias Gemuh »

Matthias Gemuh wrote:Sorry, HGM.

I got fed up with ChessGUI and forgot about our discussion.
I quoted the internal buffer stuff from here:

http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Flushing that one is blocking.
Not flushing it means the OS will flush when it deems most efficient.

Matthias.
... just to complete the thought:

If the OS flushes its internal buffer only when it deems most efficient, that steals time from engines, even if it adds up to less than 1 second per game.

My "flush" discussions have all been to establish whether there is indeed such an internal buffer _between_ WriteFile() and the pipe.
And if there is an internal buffer, whether it is responsible for any milliseconds that an engine may lose and the GUI can't account for.
And if there is an internal buffer, whether it can be forcefully flushed into the pipe in a non-blocking manner.
My engine was quite strong till I added knowledge to it.
http://www.chess.hylogic.de
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Engines lose time (not only) under ChessGUI.

Post by hgm »

For a pipe, the pipe _is_ the internal buffer. The WriteFile() call makes the user-offered data being copied to the buffer. For a real file, it would then sit there to be physically copied to the disk, at the moment this becomes possible. (But even that sis not stealing time from anyone, as everyone who wants to read the file gets the data directly from the buffer.) But for a pipe it is not waiting for anything; the OS just keeps it around in memory. As soon as there is a reader (in this case the engine) it will receive the data from this pipe buffer, and (unlike for file buffers) the data that is read will be deleted from the buffer.

So there is no stealing of any time here. On the contrary, the buffer is there to make sure the read request of the engine can be satisfied immediately, because the data is ready and waiting for it in the buffer. The buffer serves exactly the opposite purpose from what you think. It is NOT to witheld data from an engine already waiting for it (in a blocked ReadFile() call) to hand it in more efficient chunks. It is to allow the GUI to proceed when it is writing (i.e. not block the WriteFile() call), in cases the engine is not yet ready to read. So that by the time the engine is ready to read, and tells the OS so, it will not hav to wait for a blocked GUI to be set running again to think about what it would like to send to the engine. The engine only has to be blocked in its ReadFile() if it tries to read when the pipe buffer is empty. (E.g. when it is waiting for a move, but the opponent is still thinking about it.) In that case, as soon as the GUI has data and sends it in the pipe, to would unblock the engine.

Of course there is plenty of stealing of engine time by the OS in other places. That is what multi-tasking OS are for, that is what they do. In particular, engines can lose on time when they look at the clock, see that they still have 100 msec left for the last move, and decide that is enough to think some more on it, and check he clock again after 8000 nodes (which, at 1Mnps would be after 8 msec). Because, when they look at the clock after these 8000 nodes, 200 msec might have elapsed, and they ware already forfeited for 100 msec, as the OS decided to deny them the CPU for that time, because it had something better to do for it (like defragmenting the disk, or checking it for visuses...)
User avatar
Matthias Gemuh
Posts: 3245
Joined: Thu Mar 09, 2006 9:10 am

Re: Engines lose time (not only) under ChessGUI.

Post by Matthias Gemuh »

hgm wrote:For a pipe, the pipe _is_ the internal buffer. The WriteFile() call makes the user-offered data being copied to the buffer. For a real file, it would then sit there to be physically copied to the disk, at the moment this becomes possible. (But even that sis not stealing time from anyone, as everyone who wants to read the file gets the data directly from the buffer.) But for a pipe it is not waiting for anything; the OS just keeps it around in memory. As soon as there is a reader (in this case the engine) it will receive the data from this pipe buffer, and (unlike for file buffers) the data that is read will be deleted from the buffer.

So there is no stealing of any time here. On the contrary, the buffer is there to make sure the read request of the engine can be satisfied immediately, because the data is ready and waiting for it in the buffer. The buffer serves exactly the opposite purpose from what you think. It is NOT to witheld data from an engine already waiting for it (in a blocked ReadFile() call) to hand it in more efficient chunks. It is to allow the GUI to proceed when it is writing (i.e. not block the WriteFile() call), in cases the engine is not yet ready to read. So that by the time the engine is ready to read, and tells the OS so, it will not hav to wait for a blocked GUI to be set running again to think about what it would like to send to the engine. The engine only has to be blocked in its ReadFile() if it tries to read when the pipe buffer is empty. (E.g. when it is waiting for a move, but the opponent is still thinking about it.) In that case, as soon as the GUI has data and sends it in the pipe, to would unblock the engine.

Of course there is plenty of stealing of engine time by the OS in other places. That is what multi-tasking OS are for, that is what they do. In particular, engines can lose on time when they look at the clock, see that they still have 100 msec left for the last move, and decide that is enough to think some more on it, and check he clock again after 8000 nodes (which, at 1Mnps would be after 8 msec). Because, when they look at the clock after these 8000 nodes, 200 msec might have elapsed, and they ware already forfeited for 100 msec, as the OS decided to deny them the CPU for that time, because it had something better to do for it (like defragmenting the disk, or checking it for visuses...)
OK, then I have been looking for the cause of missing time in the wrong place. I am still confused, but now at a higher level.
Till I upgrade to Win64, I may never know why time forfeits occur under Win64 but hardly ever under Win32.

Thanks,
Matthias.
My engine was quite strong till I added knowledge to it.
http://www.chess.hylogic.de