compiler dependent scores!

Discussion of chess software programming and technical issues.

Moderator: Ras

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

Re: A complete and broken program

Post by bob »

jswaff wrote:
bob wrote: Every good compiler builds a dependency graph before it starts to muck around with loops. And then they ask the question "for all loop iterations i, does any single iteration i[n] depend on the results of any previous iteration completing first?" If the answer is no, then it does not matter whether the loop is executed first-to-last, last-to-first, or in completely random order.

The dependency graph will detect inter-loop dependencies and prevent this from occurring if it would cause a problem.
So in your opinion, is this a compiler bug?

--
James
No idea. It could be, based on the fact that the code you posted works on the current intel and gnu compilers with no problems other than the syntactical issues with the declaration buried in the for statement. BTW intel didn't buy that on my box so I am not sure how you compiled it on yours...
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Some assembly

Post by bob »

IA32 is right if you are running a 32 bit processor, or if you are running a 64 bit processor but using a 32 bit target. Intel has two flavors of their compiler, one for 32 bit and one for 64 bit...
jswaff

Re: A complete and broken program

Post by jswaff »

bob wrote:
Heavens no, and thank goodness the days of FORTRAN are gone. Loops like this exist in every program I have looked at:

For (i=0; i<x ;i++)
if (a < 0) break;

And then use i which points to the first element of a that is < 0...


Ok, I believe you. I'm pretty sure I had a professor tell me once that was undefined, but maybe he was referring to another language, I'm not sure.



Again, it is not the scope I am complaining about. This is fine:

for (i=i ....) {
int j, k;


}

The problem I had with your code was that this:

for (int i=0; ...) {


}

hides that int declaration pretty effectively, particularly if the rest of the for is more wordy or the termination test is more complex... I didn't like the "int" being buried in a place it is normally not found, because it makes it too easy to overlook.

So this isn't about global vs local, or even about scope. It is just about how something is declared to make it obvious what is going on...



Well, it IS about scope. Because if you don't declare the loop counter in the for loop construct (i.e. for (int i=0; ...) ) , then you have to declare it outside the body of code you intend to use it in. (Assuming you have no use for the loop counter outside the body of the loop.)

Look, you don't like it, that's fine.. my issue was with you calling it sloppy when it is considered a best practice.

--
James
Alessandro Scotti

Re: A complete and broken program

Post by Alessandro Scotti »

bob wrote:
Alessandro Scotti wrote:
jswaff wrote:I agree about the FOR loop. I assumed the loop was iterated sequentially t=1..7, so I guess that's the root problem.
James, do not blame on yourself the compiler bugs. The assumption that the loop MUST be executed sequentially is entirely correct, it's what structured programming is all about in fact.
Here the compiler thinks it knows better and fails. Happened to me once and I never used that compiler anymore, have enough of my own bugs thank you! :-)
Actually this is wrong. There is no explicit directions about order of loop execution, as you can't even guarantee that if you write in assembly language, because the processor also adds out-of-order execution to the mix. All that is required is that the data dependencies must be respected, not that the order must be maintained...
OK I think this was clear but let me rephrase it.

When you write a program in C you are instructing the computer to behave in a certain way. The computer must follow what you write, and the compiler must make sure the computer understand things correctly. If you write a loop that steps from 1 to 7 your only responsibility as a programmer is to make sure the loop works as you have programmed it. Then the compiler and the processor can use all of their trickery to make things go faster, but it's their job to ensure that it's safe to move along paths different from what has been explicitly programmed.
If the loop then fails because it's been executed 7 to 1 or parallelized or whatever, it's definitely not the programmer's fault.
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: A complete and broken program

Post by wgarvin »

bob wrote:
Alessandro Scotti wrote:
jswaff wrote:I agree about the FOR loop. I assumed the loop was iterated sequentially t=1..7, so I guess that's the root problem.
James, do not blame on yourself the compiler bugs. The assumption that the loop MUST be executed sequentially is entirely correct, it's what structured programming is all about in fact.
Here the compiler thinks it knows better and fails. Happened to me once and I never used that compiler anymore, have enough of my own bugs thank you! :-)
Actually this is wrong. There is no explicit directions about order of loop execution, as you can't even guarantee that if you write in assembly language, because the processor also adds out-of-order execution to the mix. All that is required is that the data dependencies must be respected, not that the order must be maintained...
Splitting hairs. The semantics of the loop is that it does each iteration sequentially, checking conditions at each point. Compilers can do anything they want as long as they preserve those semantics as far as the running thread is concerned. Obviously compilers sometimes optimize code in ways that change the order that it *actually* executes (even in ways that alter the data dependencies), which they are allowed to do if-and-only-if it still has the same semantics as the original sequential one as far as the single running thread is concerned. (The C/C++ execution model makes no promises to other threads, so side effects on other threads---such as writes to shared memory---might take effect in an unpredictable order or even be non-atomic or optimized away completely. Even volatile will not completely protect you there).

Edit: in a post above, Alessandro Scotti said the same thing as me except more clearly than I did.

Edit 2: based on reading the code and the descriptions posted here (I haven't actually compiled it though) I am 99% convinced that its a compiler bug. I mean, it has two different behaviours with -march=i686 and -march=pentium4 with the exact same source, and the wrong behaviour makes no sense at all after reading the code (i.e. I can't see any legit reason for it to exit the loop early, other than the compiler messed up when it generated the code).
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A complete and broken program

Post by bob »

jswaff wrote:
bob wrote:
Heavens no, and thank goodness the days of FORTRAN are gone. Loops like this exist in every program I have looked at:

For (i=0; i<x ;i++)
if (a < 0) break;

And then use i which points to the first element of a that is < 0...


Ok, I believe you. I'm pretty sure I had a professor tell me once that was undefined, but maybe he was referring to another language, I'm not sure.



Again, it is not the scope I am complaining about. This is fine:

for (i=i ....) {
int j, k;


}

The problem I had with your code was that this:

for (int i=0; ...) {


}

hides that int declaration pretty effectively, particularly if the rest of the for is more wordy or the termination test is more complex... I didn't like the "int" being buried in a place it is normally not found, because it makes it too easy to overlook.

So this isn't about global vs local, or even about scope. It is just about how something is declared to make it obvious what is going on...



Well, it IS about scope. Because if you don't declare the loop counter in the for loop construct (i.e. for (int i=0; ...) ) , then you have to declare it outside the body of code you intend to use it in. (Assuming you have no use for the loop counter outside the body of the loop.)

Look, you don't like it, that's fine.. my issue was with you calling it sloppy when it is considered a best practice.

--
James


We are still hung up in semantics...

I do not believe that "for (int i = etc...)" would be considered "best practice" by the majority of people that develop/support large systems. It makes the program significantly harder to read.

Again, this is not a comment about scope, it is about readability. I would prefer this:


{
int i;
for (i=......)
}

to

for (int i.....)

because now the scope of I is clearly visible, not buried inside an instrcution intended for looping.

So that was my only quibble with this. It is about readability, not about scope...
User avatar
Roman Hartmann
Posts: 295
Joined: Wed Mar 08, 2006 8:29 pm

Re: compiler dependent scores!

Post by Roman Hartmann »

Hi James,
I had something very similar when I switched to Linux. Ubuntu didn't install the gcc compiler by default and I had to do that manually. Somehow I suceeded in installing the wrong package for my system. I was able to compile but compiles with -O2 resulted in odd evaluation scores very much like yours. There was no problem when using no optimization or -O3. Compiles with the intel compiler resulted in segfaults as the intel compilers seems to rely on libs/headers from gcc. Installing the right gcc package solved all the problems.

Maybe you could check if you have the right compiler package and the proper libs and headers for your system.

best regards
Roman
Guetti

Re: A complete and broken program

Post by Guetti »

bob wrote:
We are still hung up in semantics...

I do not believe that "for (int i = etc...)" would be considered "best practice" by the majority of people that develop/support large systems. It makes the program significantly harder to read.

Again, this is not a comment about scope, it is about readability. I would prefer this:


{
int i;
for (i=......)
}

to

for (int i.....)

because now the scope of I is clearly visible, not buried inside an instrcution intended for looping.

So that was my only quibble with this. It is about readability, not about scope...
Ok, Mr. Hyatt. When we talk about "best practice", can you name me one book about C++, where the loop iterators are not declared in the for statement? Because that is how young people learn it and get used too.

Harder to read sounds more like C programmers that switch to C++ and just don't like it. :wink:
Tony

Re: A complete and broken program

Post by Tony »

bob wrote:
jswaff wrote:
bob wrote:I didn't have time to completely respond earlier. But here is a question:

Here are two pieces of code that do the _identically_ same computations:

Code: Select all

int EvaluateKingsFile(TREE * RESTRICT tree, int whichfile, int side)
{
  register int defects = 0, file;
  register int enemy = Flip(side);
  static const int a2a7[2] = { A7, A2 }; 
  static const int a3a6[2] = { A6, A3 };
    
  for (file = whichfile - 1; file <= whichfile + 1; file++) {
    if (!(file_mask[file] & tree->all_pawns))
      defects += open_file[file];
    else {
      if (!(file_mask[file] & Pawns(enemy)))
        defects += half_open_file[file] / 2;
      else
        defects +=
            pawn_defects[side][Rank(Advanced(enemy,
                    file_mask[file] & Pawns(enemy)))];
      if (!(file_mask[file] & Pawns(side)))
        defects += half_open_file[file];
      else {
        if (!(Pawns(side) & SetMask(a2a7[side] + file))) {
          defects++;
          if (!(Pawns(side) & SetMask(a3a6[side] + file)))
            defects++;
        }
      }
    }
  }
  return (defects);
}


and then

Code: Select all

int EvaluateKingsFile(TREE * RESTRICT tree, int whichfile, int side) { register int defects = 0, file; register int enemy = Flip(side); static const int a2a7[2] = { A7, A2 }; static const int a3a6[2] = { A6, A3 }; for (file = whichfile - 1; file <= whichfile + 1; file++) { if (!(file_mask[file] & tree->all_pawns)) defects += open_file[file]; else { if (!(file_mask[file] & Pawns(enemy))) defects += half_open_file[file] / 2; else defects += pawn_defects[side][Rank(Advanced(enemy, file_mask[file] & Pawns(enemy)))]; if (!(file_mask[file] & Pawns(side))) defects += half_open_file[file]; else { if (!(Pawns(side) & SetMask(a2a7[side] + file))) { defects++; if (!(Pawns(side) & SetMask(a3a6[side] + file))) defects++; } } } } return (defects); }


Which one is easier to read? that is what I don't like about the

for (int i=0; i<n; i++)

syntax. that "int i" is buried inside a common statement and it is easy to overlook the fact that i is local to the loop only, and if you modify i inside the loop, or break out of the loop, the value of i that is left is not the one from the loop counter, it is the i that has greater scope.
It's generally a bad idea to try to use a loop counter outside the loop anyway. IIRC the value of the loop counter when you exit the loop is undefined.
Heavens no, and thank goodness the days of FORTRAN are gone. Loops like this exist in every program I have looked at:

For (i=0; i<x ;i++)
if (a < 0) break;

And then use i which points to the first element of a that is < 0...



This might be clear programming for CSauriers ... :wink: (Hmm, how come a lot of people consider Crafty hard to read )

Nowadays something like does is more common/considered more readable. (ie split iterator and found location variable)

Code: Select all


int firstBelowZero=-1;

for (int i=0; i<x ;i++)  
{
   if (a[i] < 0) 
  {
      firstBelowZero=i;
      break;
   }
}

Some languages hide the iterator even more with a "foreach" loop.

Tony
jswaff

Re: A complete and broken program

Post by jswaff »

bob wrote:

Again, this is not a comment about scope, it is about readability. I would prefer this:


{
int i;
for (i=......)
}

to

for (int i.....)

because now the scope of I is clearly visible, not buried inside an instrcution intended for looping.

So that was my only quibble with this. It is about readability, not about scope...
Ok, I didn't catch your { } surrounding the declaration of i and the for loop, because it is so hard to read. :)

As for readability - well, I give up. You're too stubborn and set in your ways. Personally I find the "for (int i ..." type statement more readable. To each his own I guess.


--
James
Last edited by jswaff on Sat Feb 16, 2008 3:21 pm, edited 1 time in total.