View Full Version : what Intel compiler options are Koepi and/or Nic using? ICC float inaccuracies
blivit
18th April 2003, 01:55
I've got some heavily floating point intensive code that I use to do a bunch of 3D rotations of protein structures and such. I've been using GCC, but since some of these things take a long time to run, and I was going to start up a multi-week batch job, I figured I'd give the Linux ICC 7.0 a go and see if it gave me a good speed increase. Previous tests on the FLOPS 2.0 benchmark had shown very good improvements with ICC.
Well, sure enough it was faster, but the numbers at the end of the day were quite a good bit off. I looked over the Intel compiler flags, and noticed the following options controlling floating point precision:
-mp maintain floating point precision (disables some optimizations)
-mp1 improve floating-point precision (speed impact is less than -mp)
Enabling -mp1 gave me exactly the same results as GCC (well, out to 7 or 8 significant figures, which is as good as you could hope for). But this turned out to make the code even slower than GCC. -mp is HORRIBLY slow, like 2x the normal time.
So, it looks like ICC only gets such incredible speeds by cheating, throwing away a good amount of floating point precision. If you aren't using -mp1 in your ICC flags, you really should, or else video quality is going to suffer for anything involving floating point arithmetic. I don't know how much of the xvid code uses floating point instead of integer math, but you really should use -mp1 if you aren't already.
I found that "-O3 -axK -ip -mp1" gives me the best speed, without saccrificing significant floating point accuracy. But even that is still slower than GCC 3.2.2 with intelligently chosen optimization flags.
So, to sum up, if you aren't using -mp1 with ICC, you REALLY NEED TO DO SO. And also, GCC might wind up producing faster binaries than ICC with -mp1, although I have not gotten xvid to compile with it yet under cygwin + mingw32 to see if this is true or not.
-Eric
TheXung
18th April 2003, 07:43
As far as I know, xvid uses very little floating point.
Just out of curiousity, how do you know that GCC is the more accurate one? I mean the tendency is if something can be computed in less steps for that to be more accurate than something computed in lots of steps because you have less roundoff errors. Take a 3D image of something and rotate it 90 degrees in .1 increments and surely, it will be in a different place than if you rotate it 90 degrees in one step. The more accurate one is the one step.
Koepi
18th April 2003, 09:08
Ah, come on, we aren't _that_ dumb.
If PSNR between a "optimized Koepi build" and a "plain M$VC build" doesn't differ, what does that tell you?
Nice to see that you learned about the trade offs a compiler has to make for gaining speed/compact code/... , but some of us are a bit longer "in the business" and thus know all that already.
BE ASSURED THAT THOSE OPTIMIZATIONS GIVE THE SAME BRILLIANT QUALITY AS "UNOPTIMIZED BUILDS".
Hell, it's always a sh**load of work to get THAT rumour out of people's head. Thanks for that.
Koepi
blivit
18th April 2003, 22:13
TheXung: In GCC, I get the same answers no matter what optimization options I use. This is usually a sign that the math is being done correctly, or at least consistantly. Floating point optimizations often involve things like dividing 1/X, then multplying by that later rather than diving something else by X. This loses a little precision, but nothing most people will lose any sleep over. I've seen some compilers that let you enable/disable this optimization. But the difference in the Intel compiler I was seeing were much much larger than simple things like that. I'm gussing that they substitutued some floating point operations with less accurate integer math approximations. -mp and -mp1 both gave me the same answers as GCC. The -mp option is used to "maintain floating point precision (disable some optimizations)". That clearly says to me that if you don't use it, floating precision will be lost (not maintained), and that is due to some further optimizations being done. -mp1 says it will "improve floating point precision (speed impact is les than -mp". That also says to me that precision is being lost due to the standard optimizations. If GCC, -mp, and -mp1 all give me the same answers, I tend to believe that that is the correct answer, and not the answer that comes out of not using the -mpX flags. Sure, precision can be gained by some algebraic rearrangement, I won't argue that, but I think that most of the aggressive optimizations that the Intel compiler defaults to trade off WAY too much floating point precision. I would say that the chances of some floating point optimization resulting in decreased precision are a good bit higher than the chances of it increasing precision.
(edit: loop unrolling may be able to increase precision as well, since it could do exactly as TheXung said and unroll a bunch of small steps into a single jump. But I don't think that loop unrolling is one of the optimizations being disabled by -mpX)
Koepi: I belive I have seen you yourself post in the past that differneces in quality between builds were due to you changing Intel compiler optimizations. That was one of the reasons I wanted to bring this up.
blivit
18th April 2003, 22:36
Originally posted by Koepi
Nice to see that you learned about the trade offs a compiler has to make for gaining speed/compact code/... , but some of us are a bit longer "in the business" and thus know all that already.
I've been writing C code for over 10 years now. I think that counts as being "long in the business". And, being thus experienced with a wide variety of different compilers, on Suns, SGIs, Alphas, HPs, (all of the aforementioned unix systems have their own proprietary compilers), Borland, Microsoft, GCC, etc., I tend to take some things for granted, given my experience with so many different compilers. One of these assumptions is that compilers will default to reasonably conservative optimizations, ones that will not trade off very much accuracy for the sake of speed. Not even -O3 usually enables such "dangerous" optimizations, they usually require specifically enabling them. The Intel compiler deviates from this, I suspect in an attempt to inflate their benchmark scores (it worked). When I enable -O3, I expect the code to bloat up a bit in size over -O1 or -O2, but I don't expect the accuracy to go down the crapper. So, given my long experience with compilers, and assuming that others were just as well experienced, I might tend to think that others would make the same assumptions that I would, and assume that -O3 by itself was safe. It is not safe on the Intel compiler, not unless you use the -mpX flags, which are not enabled by default. Those "long in the business" should thus understand my concern :)
rjamorim
19th April 2003, 03:00
I don't buy this "Intel is cheating" BS either.
Besides, even if Intel is cheating, there's no data how it affects the final quality of encodings.
And your test details would be welcome too. We can't make any conclusion out of it without some factual data.
TheXung
19th April 2003, 08:15
Originally posted by blivit
In GCC, I get the same answers no matter what optimization options I use. This is usually a sign that the math is being done correctly, or at least consistantly. Floating point optimizations often involve things like dividing 1/X, then multplying by that later rather than diving something else by X. This loses a little precision, but nothing most people will lose any sleep over. I've seen some compilers that let you enable/disable this optimization. But the difference in the Intel compiler I was seeing were much much larger than simple things like that. I'm gussing that they substitutued some floating point operations with less accurate integer math approximations. -mp and -mp1 both gave me the same answers as GCC. The -mp option is used to "maintain floating point precision (disable some optimizations)". That clearly says to me that if you don't use it, floating precision will be lost (not maintained), and that is due to some further optimizations being done. -mp1 says it will "improve floating point precision (speed impact is les than -mp". That also says to me that precision is being lost due to the standard optimizations. If GCC, -mp, and -mp1 all give me the same answers, I tend to believe that that is the correct answer, and not the answer that comes out of not using the -mpX flags. Sure, precision can be gained by some algebraic rearrangement, I won't argue that, but I think that most of the aggressive optimizations that the Intel compiler defaults to trade off WAY too much floating point precision. I would say that the chances of some floating point optimization resulting in decreased precision are a good bit higher than the chances of it increasing precision.
I'm not going to argue with your stance because quite frankly, I don't have anything to back it up with (I never installed ICC). However I am going to point out the flaw of logic in your argument. You are reasoning that just because a compiler like GCC doesn't do many algebraic optimizations in any of it's flags, that it is more correct. That doesn't make any sense. All errors can basically be pointed to roundoff errors. It's not like there are certain numbers that produce in correct results, there aren't any fdiv bugs anymore. It's all an accumulation of roundoff errors. Say your code performs 10000 operations on a number, just because the compiler sticks to performing 10000 operations doesn't make it more correct than something that can get the answer in 5 steps.
Lets go back to the rotating an object by small increments again. You rotate it's coordinates by lots of small degrees. What you find is that it doesn't rotate around an axis but rather the axis wanders. Mathematically, the program was performing correctly; no tricky optimizations, nothing. And in a perfect precision machine, the program would run correctly, yet on computers it doesn't because of the accumlation of errors. All floating point will have some errors in them, it's a question of how to minimize them.
To sum it up
The answers are different from two compilers. You have yet to prove that one is a more correct answer. Sure you know one follows your code more exactly, but you don't know which one came out with less error.
blivit
19th April 2003, 23:37
Originally posted by TheXung
I'm not going to argue with your stance because quite frankly, I don't have anything to back it up with (I never installed ICC). However I am going to point out the flaw of logic in your argument. You are reasoning that just because a compiler like GCC doesn't do many algebraic optimizations in any of it's flags, that it is more correct. That doesn't make any sense. All errors can basically be pointed to roundoff errors.
I never made that argument. That's not my logic at all. Algebraic optimizations are very good things. GCC probably does a good number of them, as does the Intel compiler. I don't know where you got the idea I thought that optimization was a bad thing.
Lets go back to the rotating an object by small increments again. You rotate it's coordinates by lots of small degrees. What you find is that it doesn't rotate around an axis but rather the axis wanders. Mathematically, the program was performing correctly; no tricky optimizations, nothing. And in a perfect precision machine, the program would run correctly, yet on computers it doesn't because of the accumlation of errors. All floating point will have some errors in them, it's a question of how to minimize them.
Once again, I never argued this point either. If the compiler is smart enough to be able to do such optimizations, more power to it. -mp1 and -mp are very unlikely to be disabling such optimizations. By their very descriptions, they improve floating point precision, not degrade it.
The answers are different from two compilers. You have yet to prove that one is a more correct answer. Sure you know one follows your code more exactly, but you don't know which one came out with less error.
Ah, but the two different compilers DO produce the same answers, when the Intel compiler is told to maintain precision. Note, the compiler flags themselves say MAINTAIN precision, that tells you right off the bat that they default to throwing away more than you might want. Without the the -mp1 flag, it introduces more round off error than is acceptable. Maybe not in your application, maybe not in XVID (I don't know), but the fact that it did in mine tells me that it is doing something risky that probably shouldn't be used in other things either, just to be on the safe side. As you said, all floating point will have some errors in them, it's a quesiton of how to minimize them. The -mp1 flag does just that, it minimizes the round off errors without giving up too much speed. How does it differ from not using -mp1? I don't know. But I'm going to guess again that without it, it uses some faster approximations for some math functions. Like maybe the sqrt() isn't as accurate out to as many figures, or it uses some low resolution trig tables for trig functions, or fast approximations of trig functions. I have a very nice atan() equation that is good out to about 5 or 6 significant figures, which is good enough for the stuff I'm doing, just to give an example of fast approximations to math functions. I even have some example code that does a fast approximation of 1/x to avoid doing a divide (a crappy one, but one that Nvidia purportedly makes use of). There are all sorts of faster approximations of functions that can yield only a small number of significant figures. If you only use the results in a few operations, it may be acceptable. But iterate over them many times, and they add up big time. And don't go saying the compiler can magically reduce the number of rotations I have do to. No it can't, I have to search a very large amount of conformational space, and every conformation has to be scored. And no, I'm not rotating, then rotating again from that position. Each new rotation is done afresh from the original starting location, thus avoiding the cumulative roundoff errors you keep talking about. In fact, the differences in the answers came well before I even did any rotations, just measuring angles and distances between things. This points to maybe sqrt() or trig functions being approximated. Please stop trying to argue that enabling -mp1 disables all the happy optimizations that do algebraic simplifications, loop unrolling, etc.. I seriously doubt that it is disabling any of these types of optimizations, nor do I think that those types of optimizations are bad.
I haven't done enough testing to know exactly what types of math makes the default Intel flags give such lousy floating point precision. I use sqrt() a lot, and I use a bunch of trig functions. Any of those are prime candidates. I know that SGIs have options for using a sqrt table. DEC has a buttload of options for enabling sloppier floating point optimizations, which they explicitly warn you about using. None of the other compilers turn these on unless you specifically tell them to. You can't tell me that NOT using -mp1 could possibly be giving me more accurate results. If the results of using the most precise ICC flags match the results from GCC, then those are the correct results. Period. No possible argument against this. Both compilers agree with the same numbers. Not using -mpX therefore must be the wrong answer. If you don't use the options that say that they "improve" or "maintain" precision, and you get different answers, than those answers are obviously more inccorect than the ones that use "improved" or "maintained" precision. I see no way to reach any other conclusion.
Does it loose out if you are just doing simple arithmetic, like add, sub, mul, div? I don't know. It's possible, given the 1/x approximation example I have. There is an option to enable more precise divides (which I assume is included in the -mpX options too), so maybe it really is doing strange things with divides, I don't know. Maybe it doesn't affect XVID right now. I don't know that either. But I'd say it is an unacceptable risk. Just use the -mp1 flag and be safe. Most of the bottlenecks in XVID are probably either in assembly to begin with, or use all integer math. XVID will probably not lose much speed by using -mp1 over not using it. And for the rare places that do make use of floating point, at least you'll have the piece of mind of knowing that they are giving good results. The purpose of my original post wasn't to say that "this compiler has a better optimizer than this other compiler", it was simply a heads up that not using -mp1 may be dangerous, and therfore it would be advisable to enable -mp1 in any XVID builds.
I'm sorry to have gone on at such length, but I felt I had to explain myself a bit better in the face of the unexpectedly negative comments I have received thus far.
-Eric
Koepi
20th April 2003, 09:50
Well, this thread seems to be off-topic related to xvid in the meantime.
All critical calculations are done in hand-optimized and hand-written ASM/MMX/XMM/SSE/SSE2 so we take care about rounding errors if there is a possibility for them.
The only thing the compiler still can optimize is unrolling and the plain C routines which get used if you disable all CPU optimization in the XviD debug tab. Yet nobody could see any drop in PSNR when using plainC with ICL optimizations.
Thread closed. It's a very bad rumour which you spread blivit, I already got questions about xvid's precision. Thanks for that *grmblfx* :angry:
Koepi
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.