A question about thread-architecture.

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
Kempelen
Posts: 620
Joined: Fri Feb 08, 2008 10:44 am
Location: Madrid - Spain

A question about thread-architecture.

Post by Kempelen »

Hello, a question about thread-architecture:

I programmed Rodin with main thread to handle WB protocol and a thread created at startup to engine-think. I have seen engines that only uses one thread and call a kind of "bioskey" function to ask if new user/gui data is available. Is second aproach more efficient that the first for a non-SMP engine? I ask this because I have read that windows usually need CPU time when there are more than one thread to handle them propertly. Maybe that time would be useful for the engine.....

Regards
Fermin
Fermin Serrano
Author of 'Rodin' engine
http://sites.google.com/site/clonfsp/
tpetzke
Posts: 686
Joined: Thu Mar 03, 2011 4:57 pm
Location: Germany

Re: A question about thread-architecture.

Post by tpetzke »

I tried both approaches and ended up with a one similar to yours. I have a dedicated thread whose only task is to wait for new input.

This thread performs a locking read to std in. If there is no new input the thread locks and does not consume anything. If input arrives the thread wakes up and sets a flag that is polled by the main thread from time to time that new input is available.

For me this works pretty well, in Free Pascal I noticed some slowdown because declaring a thread in the program changed the internal memory handling of the compiled code into something more thread safe.

In C++ I noticed no slowdown at all.

Thomas...
mar
Posts: 2555
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: A question about thread-architecture.

Post by mar »

Kempelen wrote:Hello, a question about thread-architecture:

I programmed Rodin with main thread to handle WB protocol and a thread created at startup to engine-think. I have seen engines that only uses one thread and call a kind of "bioskey" function to ask if new user/gui data is available. Is second aproach more efficient that the first for a non-SMP engine? I ask this because I have read that windows usually need CPU time when there are more than one thread to handle them propertly. Maybe that time would be useful for the engine.....

Regards
Fermin
Hi Fermin,
I also have a separate thread for search. I see nothing wrong with that i even find it better because you don't have to poll for input from within search.
As for the second (polling) approach i don't see how it could be more efficient. If main thread processes input in a loop; then waiting for input means the thread goes idle. The only overhead I see is memory use. A thread requires its own stack (1MB default on Windows IIRC).

Martin
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A question about thread-architecture.

Post by bob »

Kempelen wrote:Hello, a question about thread-architecture:

I programmed Rodin with main thread to handle WB protocol and a thread created at startup to engine-think. I have seen engines that only uses one thread and call a kind of "bioskey" function to ask if new user/gui data is available. Is second aproach more efficient that the first for a non-SMP engine? I ask this because I have read that windows usually need CPU time when there are more than one thread to handle them propertly. Maybe that time would be useful for the engine.....

Regards
Fermin
The I/O thread idea is a good one. I don't use it because at the time, one could not do threads on MSDos. :) We used an I/O thread on Cray Blitz, which was convenient since that thread just blocks waiting on input, and it can then put the input in a buffer and send a signal to the search thread telling it to look at the data, if the I/O thread can't handle things by itself (for example, changing hash size on the fly can't happen easily with a thread searching, it will likely crash and burn, or the thread has to be told "stop searching, you are pondering the wrong move..."

I've thought about rewriting mine to be cleaner, and will do so one day as that gets rid of a lot of spaghetti that is required if you do the "check for input" approach (select() in unix, btw).
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A question about thread-architecture.

Post by bob »

mar wrote:
Kempelen wrote:Hello, a question about thread-architecture:

I programmed Rodin with main thread to handle WB protocol and a thread created at startup to engine-think. I have seen engines that only uses one thread and call a kind of "bioskey" function to ask if new user/gui data is available. Is second aproach more efficient that the first for a non-SMP engine? I ask this because I have read that windows usually need CPU time when there are more than one thread to handle them propertly. Maybe that time would be useful for the engine.....

Regards
Fermin
Hi Fermin,
I also have a separate thread for search. I see nothing wrong with that i even find it better because you don't have to poll for input from within search.
As for the second (polling) approach i don't see how it could be more efficient. If main thread processes input in a loop; then waiting for input means the thread goes idle. The only overhead I see is memory use. A thread requires its own stack (1MB default on Windows IIRC).

Martin
There's another benefit... you don't have to check the time every so often. The I/O thread can use an "alarm" type facility, or even spawn another thread that waits for a specific period of time to elapse before sending a signal to the search thread, etc.

threads sound mysterious and look difficult, but they can actually simplify the code significantly...
RoadWarrior
Posts: 73
Joined: Fri Jan 13, 2012 12:39 am
Location: London, England

Re: A question about thread-architecture.

Post by RoadWarrior »

tpetzke wrote:I tried both approaches and ended up with a one similar to yours. I have a dedicated thread whose only task is to wait for new input.
+1 for this approach, which I use in my (C#) engine. The BackgroundWorker type in the .NET Framework library makes this type of multi-threading very easy, together with the ability to do cross-thread communication of search events and controlled cancellation of the search thread.
There are two types of people in the world: Avoid them both.
Richard Allbert
Posts: 792
Joined: Wed Jul 19, 2006 9:58 am

Re: A question about thread-architecture.

Post by Richard Allbert »

I use an input Thread in Jabba.

Saw no difference in NPS with it on / off.
diep
Posts: 1822
Joined: Thu Mar 09, 2006 11:54 pm
Location: The Netherlands

Re: A question about thread-architecture.

Post by diep »

Kempelen wrote:Hello, a question about thread-architecture:

I programmed Rodin with main thread to handle WB protocol and a thread created at startup to engine-think. I have seen engines that only uses one thread and call a kind of "bioskey" function to ask if new user/gui data is available. Is second aproach more efficient that the first for a non-SMP engine? I ask this because I have read that windows usually need CPU time when there are more than one thread to handle them propertly. Maybe that time would be useful for the engine.....

Regards
Fermin
the original DOS derived Diep was just polling during search each n nodes.

What i do in Diep since 2002 is a special i/o thread that handles all user typing and it commands the search to do anything. Reason to this back then was the bit studentish assumption that some specific way to read keyboard would block this proces from search.

Even though it would be 1 out of 500 cpu's, that could stop all other 499 cpu's.

That was reason to build this special i/o thread.

In theory it is better, but it does have disadvantages.

a) you need to prove things correct
b) here is most important problem: that is that the i/o thread you don't want it to eat a full core. So basically you need to call Sleep there.

I have it sleep 10 milliseconds for example each time. Now that seems fine, except when you want to play super superbullet type games with your engine.

The sleep function will trigger regular and cause each action towards the engine to not work fast.

So for example i ran into trouble when i wanted Diep to produce 2 million evaluations with white and black reversed at a bunch of positions and then check for determinism. In Diep this is 0 ply search, as search initializes all sorts of datastructure for evaluation.

Of course that should be seconds CPU time, with just the i/o eating some big time, but it takes hours in reality, because the i/o thread sleeps, and there is a latency between it giving the engine command to start and stop the search. So instead of it taking microseconds a position it takes dozens of microseconds, just because of the communication between 2 threads.

I have yet to fix that - and i sure must fix this ASAP.

In short it is true that you offload things to a different core, but realize that there is no fast SOFTWARE mechanism to communicate between a thread that's basically always idling and a searching thread. From the searching viewpoint you want everything realtime, and the controlling thread basically has to idle.

The minimum time to wake up a thread is to schedule it in linux. Even in the realtime kernel that's pretty slow. It is in principle 10+ milliseconds simply.

So an active thread has an average responsetime of 70 microseconds in the realtime kernel. Much better than the normal kernel where it can run up to 0.5 milliseconds for an active thread.

Yet to reactivate a thread that is costly.

So realize what you're gonna do if you create a special thread for this; it means it becomes very tough to very quickly have your program produce a search, an evaluation, or anything like that.

BECAUSE the kernel basically fires at 100Hz.

You and i can't change this - databases depend upon it. So it's the same in all OS-es. A stupid limitation.

It's better in gpu's, where everything is realtime, but that's a different discussion :)

Actually in todays Diep i have default 3 threads when it runs single processor.

1 thread that's very dumb and just reads the input/keyboard/socket/TCP connection. It is blocking. 1 thread that's what i call the i/o thread, but better name would be commanding thread, it gets the keyboard input and parses it and it gives the searching processes/threads (there is no difference in diep between searching threads local and searching processes remote at shared memory machines) commands to start and stop search and it checks how long it has been thinking and based upon that commands the search to abort.

then there is the searchthread - never idles, it just reads a volatile variable to see whehter it needs to start search, then from other variables it sees whether it must initiate a search or just simply split somewhere.

becasue the command thread is idling normally, it needs to get woken up before it can do something. And we don't want it to eat much of a system time, so i give it a bunch of milliseconds to idle each time.

In your case you could get away just doing a blocking 'read the input of the user' type thread.

I really would advice you to make such a blocking thread reading stdin. As for the command thread, you might not do that yet until you're really SMP :)
mar
Posts: 2555
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: A question about thread-architecture.

Post by mar »

diep wrote: b) here is most important problem: that is that the i/o thread you don't want it to eat a full core. So basically you need to call Sleep there.

I have it sleep 10 milliseconds for example each time. Now that seems fine, except when you want to play super superbullet type games with your engine.
Hi Vincent,

I wonder why you sleep in the I/O thread? I have a plain while ( fgets() ) loop and haven't noticed the I/O thread eat any CPU time. Perhaps you read the input in a different way?
I thought that fgets on stdin should always be blocking...

Martin
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: A question about thread-architecture.

Post by Sven »

mar wrote:
diep wrote: b) here is most important problem: that is that the i/o thread you don't want it to eat a full core. So basically you need to call Sleep there.

I have it sleep 10 milliseconds for example each time. Now that seems fine, except when you want to play super superbullet type games with your engine.
Hi Vincent,

I wonder why you sleep in the I/O thread? I have a plain while ( fgets() ) loop and haven't noticed the I/O thread eat any CPU time. Perhaps you read the input in a different way?
I thought that fgets on stdin should always be blocking...

Martin
Actually I wondered about exactly the same thing. A blocking read does not eat CPU time. Sleep() is not appropriate here IMO.

Sven