Thread: RE: [GD-Windows] VC.NET 'Optimization'
Brought to you by:
vexxed72
From: Ken N. <kn...@wh...> - 2005-04-11 15:41:30
|
Yeah, I have and there is no immediate fix around this unless you want to turn all optimizations off(hence the reason it works fine in debug mode).=20 -Ken Noland -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of yogiwp Sent: Monday, April 11, 2005 9:47 AM To: gam...@li... Subject: [GD-Windows] VC.NET 'Optimization' Hi all, I've just waste alot of time debugging, and surprised that the root of problem come from VC.NET 2003 reordering stuff too aggresively. This piece of code is supposed to measure time spent in fibonacci(): ---------------------------------------------------- timer.Restart(); int fib =3D fibonacci( 42 ); float msTime =3D timer.GetElapsed(); printf( "time=3D%f, result=3D%d\n", msTime, fib ); ---------------------------------------------------- But the optimizer decided to move the fibonacci() call just before printf() and after GetElapsed(), causing the timer to measure nothing. Of course the bug does not manifest in debug builds, which made my head hurt even more :( The fix is simply changing the last line to: printf( "time=3D%f, result=3D%d\n", timer.GetElapsed(), fib ); Anyone got bitten by this before? This is a bug, right? Yogi Wahyu Prasidha ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_id=3D6595&alloc_id=3D14396&op=3Dclick _______________________________________________ Gamedevlists-windows mailing list Gam...@li... https://lists.sourceforge.net/lists/listinfo/gamedevlists-windows Archives: http://sourceforge.net/mailarchive/forum.php?forum_id=3D555 |
From: Lewin, G. <gl...@ea...> - 2005-04-12 19:02:25
|
I fail to see why this worries you, the optimiser is making a (valid) assumption about your code, and generating the fastest sequence it can. As a side note, just flip the order of your params to printf, that should give you want you want.=20 -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of yogiwp Sent: Tuesday, April 12, 2005 11:52 AM To: gam...@li... Subject: Re: [GD-Windows] VC.NET 'Optimization' ----- Original Message ----- From: Kent Quirk=20 > fib is declared locally, and no one ever takes its address. The=20 > compiler is pretty safe in assuming that no sane code could possibly=20 > affect the value of fib. Similarly, the fibonacci function only takes=20 > a constant argument. If it's in the same source file, it might even=20 > know that the function has no aliasing issues. Consequently, it's reasonable to optimize away the creation of the fib variable and simply embed the function call in the printf call. >=20 > My guess is that what the compiler did was optimize this to: >=20 > ---------------------------------------------------- > timer.Restart(); > printf( "time=3D%f, result=3D%d\n", timer.GetElapsed(), = fibonacci(42)=20 > ); > ---------------------------------------------------- Yes, this is exactly what happened (disassembly below). Sigh. I must say that this makes my worry. Btw, #pragma optimize("a",off) and/or ("w",off) have no effect; it's still generating the exact same code. Declaring msTime as 'volatile' does fix it. ------------------------------------------------------------------------ ------- ; 5215 : timer.Restart(); lea ecx, DWORD PTR _timer$[esp+148] call ?Restart@CRealTimer@Torture@@QAEXXZ ; Torture::CRealTimer::Restart ; 5216 : int fib =3D fibonacci( 42 ); ; 5217 : float msTime =3D timer.GetElapsed(); lea ecx, DWORD PTR _timer$[esp+148] call ?GetElapsed@CRealTimer@Torture@@QAEMXZ ; Torture::CRealTimer::GetElapsed push 41 ; 00000029H call ?fibonacci@@YAHH@Z ; fibonacci push 40 ; 00000028H mov edx, eax call ?fibonacci@@YAHH@Z ; fibonacci add esp, 8 add edx, eax ; 5218 : printf( "msTime=3D%f, result=3D%d\n", msTime, fib ); push edx sub esp, 8 fstp QWORD PTR [esp] push OFFSET FLAT:??_C@_0BG@BEAEGCGA@msTime?$DN?$CFf?0?5result?$DN?$CFd?6?$AA@ call _printf add esp, 16 ; 00000010H ------------------------------------------------------------------------ ------- (There are 2 fibonacci() calls because of inlining -- fibonacci() is a recursive function calling itself twice.) Yogi Wahyu Prasidha ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_id=3D6595&alloc_id=3D14396&op=3Dclick _______________________________________________ Gamedevlists-windows mailing list Gam...@li... https://lists.sourceforge.net/lists/listinfo/gamedevlists-windows Archives: http://sourceforge.net/mailarchive/forum.php?forum_id=3D555 |
From: Mat N. \(BUNGIE\) <mat...@mi...> - 2005-04-12 19:03:05
|
What worries you? The compiler optimizing out essentially dead code, or the optimization pass that destroys trivial profiling code? MSN -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of yogiwp Sent: Tuesday, April 12, 2005 11:52 AM To: gam...@li... Subject: Re: [GD-Windows] VC.NET 'Optimization' ----- Original Message -----=20 From: Kent Quirk=20 > fib is declared locally, and no one ever takes its address. The compiler is pretty safe in assuming=20 > that no sane code could possibly affect the value of fib. Similarly, the fibonacci function only=20 > takes a constant argument. If it's in the same source file, it might even know that the function has=20 > no aliasing issues. Consequently, it's reasonable to optimize away the creation of the fib variable=20 > and simply embed the function call in the printf call. >=20 > My guess is that what the compiler did was optimize this to: >=20 > ---------------------------------------------------- > timer.Restart(); > printf( "time=3D%f, result=3D%d\n", timer.GetElapsed(), = fibonacci(42) ); > ---------------------------------------------------- Yes, this is exactly what happened (disassembly below). Sigh. I must say that this makes my worry. Btw, #pragma optimize("a",off) and/or ("w",off) have no effect; it's still generating the exact same code. Declaring msTime as 'volatile' does fix it. ------------------------------------------------------------------------ ------- ; 5215 : timer.Restart(); lea ecx, DWORD PTR _timer$[esp+148] call ?Restart@CRealTimer@Torture@@QAEXXZ ; Torture::CRealTimer::Restart ; 5216 : int fib =3D fibonacci( 42 ); ; 5217 : float msTime =3D timer.GetElapsed(); lea ecx, DWORD PTR _timer$[esp+148] call ?GetElapsed@CRealTimer@Torture@@QAEMXZ ; Torture::CRealTimer::GetElapsed push 41 ; 00000029H call ?fibonacci@@YAHH@Z ; fibonacci push 40 ; 00000028H mov edx, eax call ?fibonacci@@YAHH@Z ; fibonacci add esp, 8 add edx, eax ; 5218 : printf( "msTime=3D%f, result=3D%d\n", msTime, fib ); push edx sub esp, 8 fstp QWORD PTR [esp] push OFFSET FLAT:??_C@_0BG@BEAEGCGA@msTime?$DN?$CFf?0?5result?$DN?$CFd?6?$AA@ call _printf add esp, 16 ; 00000010H ------------------------------------------------------------------------ ------- (There are 2 fibonacci() calls because of inlining -- fibonacci() is a recursive function calling itself twice.) Yogi Wahyu Prasidha ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_id=3D6595&alloc_id=3D14396&op=3Dclick _______________________________________________ Gamedevlists-windows mailing list Gam...@li... https://lists.sourceforge.net/lists/listinfo/gamedevlists-windows Archives: http://sourceforge.net/mailarchive/forum.php?forum_id=3D555 |
From: Grills, J. <jg...@so...> - 2005-04-12 19:17:33
|
Maybe on some compilers, but it's not guaranteed. The order of argument evaluation to functions is not specified by the C++ standard - it's left up to the implementations. j -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of Lewin, Gareth Sent: Tuesday, April 12, 2005 2:02 PM To: gam...@li... Subject: RE: [GD-Windows] VC.NET 'Optimization' I fail to see why this worries you, the optimiser is making a (valid) assumption about your code, and generating the fastest sequence it can. As a side note, just flip the order of your params to printf, that should give you want you want.=20 -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of yogiwp Sent: Tuesday, April 12, 2005 11:52 AM To: gam...@li... Subject: Re: [GD-Windows] VC.NET 'Optimization' > ---------------------------------------------------- > timer.Restart(); > printf( "time=3D%f, result=3D%d\n", timer.GetElapsed(), = fibonacci(42)=20 > ); > ---------------------------------------------------- |
From: Lewin, G. <gl...@ea...> - 2005-04-12 21:12:04
|
Again, the order doesn't matter, the fib function has no side effects. His goal in this specific case is to measure the speed of his fib function, so contextually changing the order the params are passed will work. If the order mattered, then fib would have been called outside the printf scope.=20 -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of Grills, Jeff Sent: Tuesday, April 12, 2005 12:17 PM To: gam...@li... Subject: RE: [GD-Windows] VC.NET 'Optimization' Maybe on some compilers, but it's not guaranteed. The order of argument evaluation to functions is not specified by the C++ standard - it's left up to the implementations. j -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of Lewin, Gareth Sent: Tuesday, April 12, 2005 2:02 PM To: gam...@li... Subject: RE: [GD-Windows] VC.NET 'Optimization' I fail to see why this worries you, the optimiser is making a (valid) assumption about your code, and generating the fastest sequence it can. As a side note, just flip the order of your params to printf, that should give you want you want.=20 -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of yogiwp Sent: Tuesday, April 12, 2005 11:52 AM To: gam...@li... Subject: Re: [GD-Windows] VC.NET 'Optimization' > ---------------------------------------------------- > timer.Restart(); > printf( "time=3D%f, result=3D%d\n", timer.GetElapsed(), = fibonacci(42)=20 > ); > ---------------------------------------------------- ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_ide95&alloc_id=14396&op=3Dick _______________________________________________ Gamedevlists-windows mailing list Gam...@li... https://lists.sourceforge.net/lists/listinfo/gamedevlists-windows Archives: http://sourceforge.net/mailarchive/forum.php?forum_idU5 |
From: Grills, J. <jg...@so...> - 2005-04-12 21:35:47
|
Perhaps I missed something earlier on since I haven't been following this thread that closely, but I don't see your point. Looking at the two code statements quoted: timer.Restart(); printf( "time=3D%f, result=3D%d\n", timer.GetElapsed(), fibonacci(42)); The compiler could call the functions in this order: timer.Restart() timer.GetElapsed() fibonacci() printf() Or it could call them in this order: timer.Restart() fibonacci() timer.GetElapsed() printf() Only the latter one would have the timer include the fibonacci() call time, because it's made between the timer.Restart() and timer.GetElapsed(). To be safe, as you said, the fibonacci() call would have to be made in a statement after the timer.Restart() but before the printf() containing the timer.GetElapsed(); j -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of Lewin, Gareth Sent: Tuesday, April 12, 2005 4:12 PM To: gam...@li... Subject: RE: [GD-Windows] VC.NET 'Optimization' Again, the order doesn't matter, the fib function has no side effects. His goal in this specific case is to measure the speed of his fib function, so contextually changing the order the params are passed will work. If the order mattered, then fib would have been called outside the printf scope.=20 -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of Grills, Jeff Sent: Tuesday, April 12, 2005 12:17 PM To: gam...@li... Subject: RE: [GD-Windows] VC.NET 'Optimization' Maybe on some compilers, but it's not guaranteed. The order of argument evaluation to functions is not specified by the C++ standard - it's left up to the implementations. j -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of Lewin, Gareth Sent: Tuesday, April 12, 2005 2:02 PM To: gam...@li... Subject: RE: [GD-Windows] VC.NET 'Optimization' I fail to see why this worries you, the optimiser is making a (valid) assumption about your code, and generating the fastest sequence it can. As a side note, just flip the order of your params to printf, that should give you want you want.=20 -----Original Message----- From: gam...@li... [mailto:gam...@li...] On Behalf Of yogiwp Sent: Tuesday, April 12, 2005 11:52 AM To: gam...@li... Subject: Re: [GD-Windows] VC.NET 'Optimization' > ---------------------------------------------------- > timer.Restart(); > printf( "time=3D%f, result=3D%d\n", timer.GetElapsed(), = fibonacci(42)=20 > ); > ---------------------------------------------------- |
From: Jon W. <hp...@mi...> - 2005-04-12 22:15:04
|
> To be safe, as you said, the fibonacci() call would have to be made in a > statement after the timer.Restart() but before the printf() containing > the timer.GetElapsed(); This still doesn't fix the problem that, given that you pass a constant into fibonacci(), the compiler can statically evaluate the entire function and replace it with a literal value. Cheers, / h+ |