.com.unity Forums

.com.unity Forums (http://forum.shrapnelgames.com/index.php)
-   Dominions 2: The Ascension Wars (http://forum.shrapnelgames.com/forumdisplay.php?f=55)
-   -   2.08 and Incompatible Battle Reports (http://forum.shrapnelgames.com/showthread.php?t=17878)

General Tacticus February 26th, 2004 10:52 AM

Re: 2.08 and Incompatible Battle Reports
 
How about :

a = 2d6;
b = 2d6;
if ( x + a < y + b ) ...

Don't tell me there's a compiler around daft enough to evaluate b before a in this case !

Arryn February 26th, 2004 10:55 AM

Re: 2.08 and Incompatible Battle Reports
 
Quote:

Originally posted by General Tacticus:
How about :

a = 2d6;
b = 2d6;
if ( x + a < y + b ) ...

Don't tell me there's a compiler around daft enough to evaluate b before a in this case !

<font size="2" face="sans-serif, arial, verdana">This should work just fine, under normal conditions.

EDIT: caveat: it actually is possible to force the compilers I've used into screwing this up. It involves tweaking settings so the compiler re-orders the statements so that it reads ...

b = a = 2d6

Which, of course, looks the same as your example to anyone who's not a gamer or mathematician. We know that 2 calls to "d6" do not necessarily return the same answer. http://forum.shrapnelgames.com/images/icons/icon12.gif

[ February 26, 2004, 09:01: Message edited by: Arryn ]

General Tacticus February 26th, 2004 11:37 AM

Re: 2.08 and Incompatible Battle Reports
 
Quote:

Originally posted by Arryn:


EDIT: caveat: it actually is possible to force the compilers I've used into screwing this up. It involves tweaking settings so the compiler re-orders the statements so that it reads ...

b = a = 2d6

Which, of course, looks the same as your example to anyone who's not a gamer or mathematician. We know that 2 calls to "d6" do not necessarily return the same answer. http://forum.shrapnelgames.com/images/icons/icon12.gif

<font size="2" face="sans-serif, arial, verdana">And you can also make them believe that '<' means '>', or for that matter that "=" in the code means 'print("I'm a genius")' http://forum.shrapnelgames.com/images/icons/icon12.gif . But we are here to help compilers do the right thing, not to screw their settings and help them be total idiots http://forum.shrapnelgames.com/images/icons/icon7.gif

Arryn February 26th, 2004 11:41 AM

Re: 2.08 and Incompatible Battle Reports
 
Quote:

Originally posted by General Tacticus:
... and help them be total idiots http://forum.shrapnelgames.com/images/icons/icon7.gif
<font size="2" face="sans-serif, arial, verdana">This is just too good to resist: as opposed to what they would otherwise be? (less-than-total idiots) http://forum.shrapnelgames.com/images/icons/tongue.gif http://forum.shrapnelgames.com/images/icons/tongue.gif http://forum.shrapnelgames.com/images/icons/icon12.gif

Johan K February 26th, 2004 12:03 PM

Re: 2.08 and Incompatible Battle Reports
 
Quote:

Originally posted by General Tacticus:
How about :

a = 2d6;
b = 2d6;
if ( x + a < y + b ) ...

<font size="2" face="sans-serif, arial, verdana">That's the one that is used now. Easy to read and it should be foolproof.

PhilD February 26th, 2004 12:14 PM

Re: 2.08 and Incompatible Battle Reports
 
Quote:

Originally posted by General Tacticus:
And you can also make them believe that '<' means '>', or for that matter that "=" in the code means 'print("I'm a genius")' http://forum.shrapnelgames.com/images/icons/icon12.gif . But we are here to help compilers do the right thing, not to screw their settings and help them be total idiots http://forum.shrapnelgames.com/images/icons/icon7.gif
<font size="2" face="sans-serif, arial, verdana">You've obviously never had to work on optimizing a compiler... (neither have I, but I do occasionally teach some programming)

Warning: Tech speak coming up. If you're only into computer games and not programming, maybe you should skip this. Well, maybe you should skip the whole thread, apart from the "we found the bug and it will be corrected in the next patch" bit.

If your function calls are guaranteed to not have any side effects, the rearrangement Arryn "suggested" is actually a good move; it makes the compiled program faster by saving a (potentially costly) function call. This is a case of the compiler "helping" a sloppy programmer (and all programmers are sloppy).

Of course, if your function call has a side effect, it's a very bad move because one call will not have the same side effect as two calls. In this case, calling the dice-rolling function has a side effect, since it modifies the state of the random generator, so it's pretty important.

I don't know enough of the C specification to say whether there's a keyword to let the compiler know that a given function call is guaranteed to not have any side effects, but I suppose some compilers can be tweaked to assume that they are...

[And I don't even know whether "side effect" is the correct English translation for the French "effet de bord"; all my teaching is done in French, I admit...]

Arryn February 26th, 2004 12:32 PM

Re: 2.08 and Incompatible Battle Reports
 
Philippe, "side effect" is the correct translation, AFAIK.

And I'm glad that at least one person who's been reading this thread "gets it" with regards to compiler optimization, and possible pitfalls. Thanks for posting.

BTW, AFAIK, there aren't any C/C++ keywords that affect the sort of optimizations that can cause these troubles. The best way to avoid them is understanding how functions pass back values, most importantly, what all the various optimization switches do (and which ones you have turned "on"), and how the compiler actually optimizes the code (which is done at the assembly-code level, not source-code level).

Breaking complex expressions into separate and simple statements will go a long ways to avoiding possible problems too. It takes a little longer to write the code, but the end result is easier to read and maintain.

BugRoger February 26th, 2004 01:17 PM

Re: 2.08 and Incompatible Battle Reports
 
Perfect. Thank you guys for hunting this bug down. I got a freshly installed Debian 24/7 server waiting for the next patch... http://forum.shrapnelgames.com/images/icons/icon12.gif

alexti February 26th, 2004 03:12 PM

Re: 2.08 and Incompatible Battle Reports
 
Quote:

Originally posted by PhilD:
If your function calls are guaranteed to not have any side effects, the rearrangement Arryn "suggested" is actually a good move; it makes the compiled program faster by saving a (potentially costly) function call. This is a case of the compiler "helping" a sloppy programmer (and all programmers are sloppy).

Of course, if your function call has a side effect, it's a very bad move because one call will not have the same side effect as two calls. In this case, calling the dice-rolling function has a side effect, since it modifies the state of the random generator, so it's pretty important.

I don't know enough of the C specification to say whether there's a keyword to let the compiler know that a given function call is guaranteed to not have any side effects, but I suppose some compilers can be tweaked to assume that they are...

[And I don't even know whether "side effect" is the correct English translation for the French "effet de bord"; all my teaching is done in French, I admit...]

<font size="2" face="sans-serif, arial, verdana">I'd say you translated "side effect" correctly, but in the context it sounds like the calls
</font><blockquote><font size="1" face="sans-serif, arial, verdana">code:</font><hr /><pre style="font-size:x-small; font-family: monospace;"> time_t t1 = time(0);
time_t t2 = time(0);</pre><hr /></blockquote><font size="2" face="sans-serif, arial, verdana">should not be optimized because function time has a "side effect" of returning the current time.

I understand that you're talking about the functions which are function in mathematic sense, meaning that for a given set of arguments the result will always be the same, and the return value will be the only data that will be changed.
I don't know if there's a term for such functions.

The problem comes because optimizer can not really figure out if the function has any "side effects" (let's keep calling them this way). Compiling/optimizing are performed per compilation unit and if the function in question is not residing in the same unit, optimizer can't even try to analyse the function, so it has no choice but make 2 separate calls.

Are there any optimizer which would try to do this kind of optimization? Usually, they just optimize common subexpressions, for
</font><blockquote><font size="1" face="sans-serif, arial, verdana">code:</font><hr /><pre style="font-size:x-small; font-family: monospace;"> a1 = 4 + (x + y)*n;
b1 = 8 + (x + y)*n;</pre><hr /></blockquote><font size="2" face="sans-serif, arial, verdana">they would evaluate (x+y)*n once, leave it in the register and then do additions and assignments.

This method isn't safe either, consider:
</font><blockquote><font size="1" face="sans-serif, arial, verdana">code:</font><hr /><pre style="font-size:x-small; font-family: monospace;"> void foo(int&amp; a1, int&amp; b1, int&amp; x, int y, int n)
{
a1 = 4 + (x + y)*n;
b1 = 8 + (x + y)*n;
}

void ouch()
{
int z, x = 1, y = 1, n = 2;
foo(x,z,x,y,n);
}</pre><hr /></blockquote><font size="2" face="sans-serif, arial, verdana">Though for this case the optimizer often has some kind of pragmas that allow to tell that the function does not have any aliased variables.

alexti February 26th, 2004 03:25 PM

Re: 2.08 and Incompatible Battle Reports
 
Quote:

Originally posted by Arryn:
BTW, AFAIK, there aren't any C/C++ keywords that affect the sort of optimizations that can cause these troubles. The best way to avoid them is understanding how functions pass back values, most importantly, what all the various optimization switches do (and which ones you have turned "on"), and how the compiler actually optimizes the code (which is done at the assembly-code level, not source-code level).
<font size="2" face="sans-serif, arial, verdana">The idea of the standards is to be able to write code which will work correctly (meaning that as programmer specified in the source code - as opposite to what the programmer wants http://forum.shrapnelgames.com/images/icons/icon12.gif ) if compiled by any standard-compliant compiler. Optimizer should meet all criteria defined in the language standard concerning the produced binary code, so the only case when it is allowed to alter the results is when the programmer is using constructs which behaviour is undefined by the standard. And the programmer should not be using such constructs.

If one had to examing the code and switches for each particular optimizer, he'd better just optimize the source code.

Of course, if one needs to compile something with particular compiler and that compiler is broken, that's bad luck http://forum.shrapnelgames.com/images/icons/icon9.gif

And if using MSVC5/6 one can optimize for size, it often produces faster code then optimization for speed (even if speed-optimized executable is sort of working).


All times are GMT -4. The time now is 08:35 AM.

Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Copyright ©1999 - 2025, Shrapnel Games, Inc. - All Rights Reserved.