trick question

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: trick question

Post by jwes »

mar wrote:
Aleks Peshkov wrote:The trick is to use second counter.
for IO, I'd use a separate thread (main thread IO, search in a separate thread
for the timeout, however, I'd still use polling
I use one thread for input which blocks and one thread which waits for an input line, a search result, or a timeout. The search routine has a test, if (AbortSearch){...}, at the top. I believe this reduces overhead to one well predicted jump.
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: trick question

Post by AlvaroBegue »

jwes wrote:
mar wrote:
Aleks Peshkov wrote:The trick is to use second counter.
for IO, I'd use a separate thread (main thread IO, search in a separate thread
for the timeout, however, I'd still use polling
I use one thread for input which blocks and one thread which waits for an input line, a search result, or a timeout. The search routine has a test, if (AbortSearch){...}, at the top. I believe this reduces overhead to one well predicted jump.
That's very clean, and doesn't require anything outside the C++ standard, like checking if there is input without blocking.

However, you probably need to make AbortSearch atomic for the code to be correct. [DISCLAIMER: I don't fully understand all the details and gotchas involved in multi-thread programming.]
Daniel Shawul
Posts: 4185
Joined: Tue Mar 14, 2006 11:34 am
Location: Ethiopia

Re: trick question

Post by Daniel Shawul »

Thanks for the math, i had fun at work with my colleagues with this seemingly easy problem. Somebody actually noticed that you shouldn't be adding an even or odd number all the time so it the number_of_moves is
a uniformly distributed random number between 1-40

I noticed this issue when i had time failures for the MCTS search, which i thought shouldn't happen since the number of playouts is bing increased by 1 every time.
At some point i changed it so that all children at the leaves of a single parent are visited, thereby causing a problem for the (visits % 200) == 0 test i had
jwes
Posts: 778
Joined: Sat Jul 01, 2006 7:11 am

Re: trick question

Post by jwes »

AlvaroBegue wrote:
jwes wrote:
mar wrote:
Aleks Peshkov wrote:The trick is to use second counter.
for IO, I'd use a separate thread (main thread IO, search in a separate thread
for the timeout, however, I'd still use polling
I use one thread for input which blocks and one thread which waits for an input line, a search result, or a timeout. The search routine has a test, if (AbortSearch){...}, at the top. I believe this reduces overhead to one well predicted jump.
That's very clean, and doesn't require anything outside the C++ standard, like checking if there is input without blocking.

However, you probably need to make AbortSearch atomic for the code to be correct. [DISCLAIMER: I don't fully understand all the details and gotchas involved in multi-thread programming.]
I only write to this variable from one thread and do not care if it is read wrong once (as long as it is either the old value or the new value). I believe that is enough. If it is not, I hope someone will explain it to me.
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: trick question

Post by AlvaroBegue »

jwes wrote:I only write to this variable from one thread and do not care if it is read wrong once (as long as it is either the old value or the new value). I believe that is enough. If it is not, I hope someone will explain it to me.
I'll try to explain what I understand. If it's not atomic, a thread might feel free to do something like keeping its value in a register and not read it from memory the next time around. The compiler could also analyze your code, realize that no part of the code in this thread can possibly change the value of the variable and optimize your test out.

My guess is that these are not of any practical concern at this time, but it's the kind of thing that might change in 5 years when compilers get smarter, and then you'll be screaming "This has worked fine for years, and I don't see why they had to come and break it!", and you'll be wrong. The language standard specifies what is guaranteed to work, and this probably isn't.

Then again, I might be completely wrong and I would appreciate input from someone with more experience, or from a someone with programming-language-lawyer abilities.
elcabesa
Posts: 855
Joined: Sun May 23, 2010 1:32 pm

Re: trick question

Post by elcabesa »

AlvaroBegue wrote:
jwes wrote:I only write to this variable from one thread and do not care if it is read wrong once (as long as it is either the old value or the new value). I believe that is enough. If it is not, I hope someone will explain it to me.
I'll try to explain what I understand. If it's not atomic, a thread might feel free to do something like keeping its value in a register and not read it from memory the next time around. The compiler could also analyze your code, realize that no part of the code in this thread can possibly change the value of the variable and optimize your test out.

My guess is that these are not of any practical concern at this time, but it's the kind of thing that might change in 5 years when compilers get smarter, and then you'll be screaming "This has worked fine for years, and I don't see why they had to come and break it!", and you'll be wrong. The language standard specifies what is guaranteed to work, and this probably isn't.

Then again, I might be completely wrong and I would appreciate input from someone with more experience, or from a someone with programming-language-lawyer abilities.
Your concerning are resolved by the keyword "volatile".
It tell the compiler and optimizer that the variable value can be changed from outside the visibility of the compiler, so the compiler has to use the standard rules to access the variable. Read it as: it has to read the variable from ram on every access. The volatile keyword is present in c and c++ from the first versions
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: trick question

Post by AlvaroBegue »

elcabesa wrote:
AlvaroBegue wrote:
jwes wrote:I only write to this variable from one thread and do not care if it is read wrong once (as long as it is either the old value or the new value). I believe that is enough. If it is not, I hope someone will explain it to me.
I'll try to explain what I understand. If it's not atomic, a thread might feel free to do something like keeping its value in a register and not read it from memory the next time around. The compiler could also analyze your code, realize that no part of the code in this thread can possibly change the value of the variable and optimize your test out.

My guess is that these are not of any practical concern at this time, but it's the kind of thing that might change in 5 years when compilers get smarter, and then you'll be screaming "This has worked fine for years, and I don't see why they had to come and break it!", and you'll be wrong. The language standard specifies what is guaranteed to work, and this probably isn't.

Then again, I might be completely wrong and I would appreciate input from someone with more experience, or from a someone with programming-language-lawyer abilities.
Your concerning are resolved by the keyword "volatile".
It tell the compiler and optimizer that the variable value can be changed from outside the visibility of the compiler, so the compiler has to use the standard rules to access the variable. Read it as: it has to read the variable from ram on every access. The volatile keyword is present in c and c++ from the first versions
And yet the Internet is full of messages advising people to not use volatile for synchronization between threads. See the first answer here, for instance: https://stackoverflow.com/questions/248 ... rogramming
Ras
Posts: 2487
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: trick question

Post by Ras »

AlvaroBegue wrote:I'll try to explain what I understand. If it's not atomic, a thread might feel free to do something like keeping its value in a register and not read it from memory the next time around.
I think you are mixing up atomic and volatile. They have nothing to do with each other.
User avatar
hgm
Posts: 27796
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: trick question

Post by hgm »

It seems that all accesses to volatile variables are forced to be actually made, and in program order. If that is true, I don't see how anything could go wrong if all data shared between threads is declared as volatile.

When volatile flags would be used in an attempt to synchronize access to non-volatile data, this just seems improper use to me, rather than an intrinsic shortcoming of the 'volatile' concept.
elcabesa
Posts: 855
Joined: Sun May 23, 2010 1:32 pm

Re: trick question

Post by elcabesa »

AlvaroBegue wrote:
I'll try to explain what I understand. If it's not atomic, a thread might feel free to do something like keeping its value in a register and not read it from memory the next time around. The compiler could also analyze your code, realize that no part of the code in this thread can possibly change the value of the variable and optimize your test out.
AlvaroBegue wrote:
And yet the Internet is full of messages advising people to not use volatile for synchronization between threads. See the first answer here, for instance: https://stackoverflow.com/questions/248 ... rogramming
I haven't said that syncronization between threads can be achieved by using the "volatile" keyword. I only say that if you want to avoid this situation:
The compiler could also analyze your code, realize that no part of the code in this thread can possibly change the value of the variable and optimize your test out.
the keyword to be used is "volatile", atomic is another concept and is also used in multithreading programming.

I was simply trying to explain you that you were mixing concept. volatile and atomic. and that atomic and volatile are both use in multithreading but are not the same concept.

Volatile is necessary for multithreading, but it's not enough