Move time and compiler optimization

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Edmund
Posts: 670
Joined: Mon Dec 03, 2007 3:01 pm
Location: Barcelona, Spain

Move time and compiler optimization

Post by Edmund »

When the engine receives the go command, it stores the current system time, then it starts the search and every certain number of nodes it checks whether the (current system time) - (initial system time) > (maximum move time). I need the current system time to be as accurate as possible to keep safety time buffers as small as possible and also not risk running out of time.

I would have something like:

Code: Select all

blocked wait for message
if (message == go) intial_time = system_time();
Now I wonder whether there exists the risk of compilers reordering instructions; and if so, what can we do about this.

scenario 1:

Code: Select all

r1 = system_time();
blocked wait for message
if (message == go) intial_time = r1;
scenario 2:

Code: Select all

blocked wait for message
<do other stuff here>
if &#40;message == go&#41; intial_time = system_time&#40;);
User avatar
hgm
Posts: 27796
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Move time and compiler optimization

Post by hgm »

Scenario 1 is certainly impossible. In scenario 2 it coulld never do something significant before reading the clock, like a function call. A compiler cannot reorder functions when it doesn't know what they do.
Daniel Shawul
Posts: 4185
Joined: Tue Mar 14, 2006 11:34 am
Location: Ethiopia

Re: Move time and compiler optimization

Post by Daniel Shawul »

Hi Edmund I don't think compilers will reorder instructions that will break code in an obvious way such as this one. Out of order execution is used to avoid pipeline stalls due to data unavailability. A single line of code (e.g x++) is broken down to many instructions on which pipelining and reordering occurs, not at a larger scale that will re-order system-time call with wait_for_messages.
But my knowlege about the topic is limite.
syzygy
Posts: 5563
Joined: Tue Feb 28, 2012 11:56 pm

Re: Move time and compiler optimization

Post by syzygy »

Both receiving I/O and reading system_time involve side effects. A compiler is not allowed to reorder side effects across sequence points. There are sequence points between "blocked wait for message" and the evaluation of "message == go" and between the evaluation of "message == go" and "inital_time = system_time()".

So scenario 1 is impossible.

Scenario 2 is possible in so far as the compiler can determine that "other stuff" has no side effects.
mar
Posts: 2555
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Move time and compiler optimization

Post by mar »

Hello Edmund,
as far as I know function calls (whether inline or not) are sequence points (as defined by the standard) so I wouldn't worry there (plus arguments are guaranteed to be evaluated before function body is entered).

A real-life example that happened to me some time ago:

Code: Select all

    	nodes&#91;res&#93;.index = addNode&#40; n->front );
where nodes is a vector that can be changed by subsequent call to recursive method addNode.
What happened is that the compiler cached pointer to nodes before calling addNode which pushes back some elements (sure I might have preallocated nodes in advance by using pre-traversal).
It's because the order of evaluation of assignment operator is not guaranteed (it's not a sequence point unlike && and || operators which are guaranteed to evaluate left to right),
so the compiler is free to evaluate left side first (read where to store the result, not the store itself).

Fixing it was simple enough:

Code: Select all

        int tmp = addNode&#40; n->front );
        nodes&#91;res&#93;.index = tmp;
One has to be careful sometimes :)
From what I've read sequence points are also automatically "inserted" at the end of each expression statement.

Hope it helps.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Move time and compiler optimization

Post by bob »

mar wrote:Hello Edmund,
as far as I know function calls (whether inline or not) are sequence points (as defined by the standard) so I wouldn't worry there (plus arguments are guaranteed to be evaluated before function body is entered).

A real-life example that happened to me some time ago:

Code: Select all

    	nodes&#91;res&#93;.index = addNode&#40; n->front );
where nodes is a vector that can be changed by subsequent call to recursive method addNode.
What happened is that the compiler cached pointer to nodes before calling addNode which pushes back some elements (sure I might have preallocated nodes in advance by using pre-traversal).
It's because the order of evaluation of assignment operator is not guaranteed (it's not a sequence point unlike && and || operators which are guaranteed to evaluate left to right),
so the compiler is free to evaluate left side first (read where to store the result, not the store itself).

Fixing it was simple enough:

Code: Select all

        int tmp = addNode&#40; n->front );
        nodes&#91;res&#93;.index = tmp;
One has to be careful sometimes :)
From what I've read sequence points are also automatically "inserted" at the end of each expression statement.

Hope it helps.
That statement leaves a lot to be desired. "each expression statement" means what when a compiler has taken the instructions from several consecutive source statements and interlaced them like a drunken programmer? The concept "sequence point" is extremely vague when you get down to actual programming and the compiler. Fortunately an accurate data flow graph (which any optimizing compiler produces as a natural work product) takes care of this funny stuff.
syzygy
Posts: 5563
Joined: Tue Feb 28, 2012 11:56 pm

Re: Move time and compiler optimization

Post by syzygy »

bob wrote:
mar wrote:Hello Edmund,
as far as I know function calls (whether inline or not) are sequence points (as defined by the standard) so I wouldn't worry there (plus arguments are guaranteed to be evaluated before function body is entered).

A real-life example that happened to me some time ago:

Code: Select all

    	nodes&#91;res&#93;.index = addNode&#40; n->front );
where nodes is a vector that can be changed by subsequent call to recursive method addNode.
What happened is that the compiler cached pointer to nodes before calling addNode which pushes back some elements (sure I might have preallocated nodes in advance by using pre-traversal).
It's because the order of evaluation of assignment operator is not guaranteed (it's not a sequence point unlike && and || operators which are guaranteed to evaluate left to right),
so the compiler is free to evaluate left side first (read where to store the result, not the store itself).

Fixing it was simple enough:

Code: Select all

        int tmp = addNode&#40; n->front );
        nodes&#91;res&#93;.index = tmp;
One has to be careful sometimes :)
From what I've read sequence points are also automatically "inserted" at the end of each expression statement.

Hope it helps.
That statement leaves a lot to be desired. "each expression statement" means what when a compiler has taken the instructions from several consecutive source statements and interlaced them like a drunken programmer? The concept "sequence point" is extremely vague when you get down to actual programming and the compiler. Fortunately an accurate data flow graph (which any optimizing compiler produces as a natural work product) takes care of this funny stuff.
You do not have to show that you have no clue about the C standard.
AlvaroBegue
Posts: 931
Joined: Tue Mar 09, 2010 3:46 pm
Location: New York
Full name: Álvaro Begué (RuyDos)

Re: Move time and compiler optimization

Post by AlvaroBegue »

bob wrote:
mar wrote:Hello Edmund,
as far as I know function calls (whether inline or not) are sequence points (as defined by the standard) so I wouldn't worry there (plus arguments are guaranteed to be evaluated before function body is entered).

A real-life example that happened to me some time ago:

Code: Select all

    	nodes&#91;res&#93;.index = addNode&#40; n->front );
where nodes is a vector that can be changed by subsequent call to recursive method addNode.
What happened is that the compiler cached pointer to nodes before calling addNode which pushes back some elements (sure I might have preallocated nodes in advance by using pre-traversal).
It's because the order of evaluation of assignment operator is not guaranteed (it's not a sequence point unlike && and || operators which are guaranteed to evaluate left to right),
so the compiler is free to evaluate left side first (read where to store the result, not the store itself).

Fixing it was simple enough:

Code: Select all

        int tmp = addNode&#40; n->front );
        nodes&#91;res&#93;.index = tmp;
One has to be careful sometimes :)
From what I've read sequence points are also automatically "inserted" at the end of each expression statement.

Hope it helps.
That statement leaves a lot to be desired. "each expression statement" means what when a compiler has taken the instructions from several consecutive source statements and interlaced them like a drunken programmer? The concept "sequence point" is extremely vague when you get down to actual programming and the compiler. Fortunately an accurate data flow graph (which any optimizing compiler produces as a natural work product) takes care of this funny stuff.
Didn't you use to teach this language in college? And you think there is something vague about sequence points? Good lord...
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Move time and compiler optimization

Post by bob »

syzygy wrote:
bob wrote:
mar wrote:Hello Edmund,
as far as I know function calls (whether inline or not) are sequence points (as defined by the standard) so I wouldn't worry there (plus arguments are guaranteed to be evaluated before function body is entered).

A real-life example that happened to me some time ago:

Code: Select all

    	nodes&#91;res&#93;.index = addNode&#40; n->front );
where nodes is a vector that can be changed by subsequent call to recursive method addNode.
What happened is that the compiler cached pointer to nodes before calling addNode which pushes back some elements (sure I might have preallocated nodes in advance by using pre-traversal).
It's because the order of evaluation of assignment operator is not guaranteed (it's not a sequence point unlike && and || operators which are guaranteed to evaluate left to right),
so the compiler is free to evaluate left side first (read where to store the result, not the store itself).

Fixing it was simple enough:

Code: Select all

        int tmp = addNode&#40; n->front );
        nodes&#91;res&#93;.index = tmp;
One has to be careful sometimes :)
From what I've read sequence points are also automatically "inserted" at the end of each expression statement.

Hope it helps.
That statement leaves a lot to be desired. "each expression statement" means what when a compiler has taken the instructions from several consecutive source statements and interlaced them like a drunken programmer? The concept "sequence point" is extremely vague when you get down to actual programming and the compiler. Fortunately an accurate data flow graph (which any optimizing compiler produces as a natural work product) takes care of this funny stuff.
You do not have to show that you have no clue about the C standard.
If you knew 1/2 of what you think you know, you'd stay out of these conversations with your cute one-liners...
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Move time and compiler optimization

Post by bob »

AlvaroBegue wrote:
bob wrote:
mar wrote:Hello Edmund,
as far as I know function calls (whether inline or not) are sequence points (as defined by the standard) so I wouldn't worry there (plus arguments are guaranteed to be evaluated before function body is entered).

A real-life example that happened to me some time ago:

Code: Select all

    	nodes&#91;res&#93;.index = addNode&#40; n->front );
where nodes is a vector that can be changed by subsequent call to recursive method addNode.
What happened is that the compiler cached pointer to nodes before calling addNode which pushes back some elements (sure I might have preallocated nodes in advance by using pre-traversal).
It's because the order of evaluation of assignment operator is not guaranteed (it's not a sequence point unlike && and || operators which are guaranteed to evaluate left to right),
so the compiler is free to evaluate left side first (read where to store the result, not the store itself).

Fixing it was simple enough:

Code: Select all

        int tmp = addNode&#40; n->front );
        nodes&#91;res&#93;.index = tmp;
One has to be careful sometimes :)
From what I've read sequence points are also automatically "inserted" at the end of each expression statement.

Hope it helps.
That statement leaves a lot to be desired. "each expression statement" means what when a compiler has taken the instructions from several consecutive source statements and interlaced them like a drunken programmer? The concept "sequence point" is extremely vague when you get down to actual programming and the compiler. Fortunately an accurate data flow graph (which any optimizing compiler produces as a natural work product) takes care of this funny stuff.
Didn't you use to teach this language in college? And you think there is something vague about sequence points? Good lord...

edit: duplicate post deleted. Apparently my macbook thought I hit submit before I was finished typing.
Last edited by bob on Thu Mar 27, 2014 9:20 pm, edited 2 times in total.