[MDEV-12796] Bad DOUBLE retruned when built with gcc -ffast-math [strings/dtoa.c issue?] Created: 2017-05-15 Updated: 2017-05-29 Resolved: 2017-05-29 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Compiling |
| Affects Version/s: | 10.1.19, 10.1.22, 10.1.23 |
| Fix Version/s: | N/A |
| Type: | Bug | Priority: | Major |
| Reporter: | Tech Magos | Assignee: | Sergei Golubchik |
| Resolution: | Won't Fix | Votes: | 0 |
| Labels: | -ffast-math | ||
| Environment: |
Linux RHEL 7.x ; also 6.x All versions of mariadb since 10.0 to current 10.1 |
||
| Description |
|
A linux/gcc (4.4 or 4.8 or 5.3) optimized build fails returning correct correct values for DOUBLE cells. To repro: 1. make a gcc optimized build; flags -march=native -O3 -mavx -mfpmath=sse -msse2 -msse4 -fomit-frame-pointer -ffast-math 2. Create a table with a single DOUBLE field. 3. Insert a number like 132 bill (132000000000) . Select it back and you will get non numeric output (a ":" or other character will appear in the number returned) The problem goes away when you build without the -ffast-math flag is not used The problem appears to be in dtoa.c in strings/ I believe code should work properly, even when --fast-math is passed. – As an aside, there are faster publicly available atod and dtoa options (as well as itoa and atoi) compare to the ones mariadb uses. Those could give notable speedup for both server and client code and should be possibly reviewed and considered. See e.g.: |
| Comments |
| Comment by Elena Stepanova [ 2017-05-20 ] | |||||||||||||||||||||||||
|
Note: I didn't check other versions. | |||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2017-05-23 ] | |||||||||||||||||||||||||
|
I tend to say that it is not a bug. -ffast-math enables -funsafe-math-optimizations, which is documented as
And -funsafe-math-optimizations enables -freciprocal-math:
And this is exactly what is happening. When dtoa is compiled without reciprocal math, the code is
during the execution, %xmm2 is 320000000000, %xmm4 is 100000000000, the result is 3.2.
where %xmm2 is 320000000000, and %xmm6 is 100000000000. This trick loses precision, as documented, and the result is 3.1999999999999997. While the digit 3 is still corectly appended to the result string, the next two digits will be not 2 and 0, but 1 and 10 (that is ':'). So, apparently, dtoa relies on the correct IEEE standard behavior and does not tolerate precision loss caused by reciprocal math optimization. | |||||||||||||||||||||||||
| Comment by Tech Magos [ 2017-05-27 ] | |||||||||||||||||||||||||
|
mariadb is built and will be built with the -ffast-math flag (online forums reveal so too). To avoid people hitting problems in the future, you could perhaps disable the relevant gcc optim in dtoa (with a pragma)? Or more agressive, you could #error if the flag is passed (GCC sets a macro if this is enabled) Unrelated to this bug, but related to dtoa.c, it may be worth to spend some time researching the upgrading of double<->string and int<->string conversion functions in mariadb. There is a large hidden optimization possible here for both server + client: number<->text conversions happen a lot across the text protocol. Example codes (among others on github): https://github.com/miloyip/dtoa-benchmark (which may also not have the -ffast-math issue) | |||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2017-05-28 ] | |||||||||||||||||||||||||
|
What do you mean by “mariadb is built and will be built with the -ffast-math”? Our packages are not built with -ffast-math. Do you mean RHEL packages? Checking __FAST_MATH__ is rather imprecise. dtoa cares about -freciprocal-math. One can enable only the latter, and __FAST_MATH__ won't be set. Or one can enable fast math, but disable reciprocal math. I'll see if I can disable reciprocal math for dtoa. Yes, other dtoa implementations are certainly worth exploring. Just not within the scope of this issue. | |||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2017-05-28 ] | |||||||||||||||||||||||||
|
I've found three issues so far. One is that you said,
But there are more:
And even that is not enough, it seems that isinf() is not working properly with -ffast-math, so MariaDB crashes on some tests, being unable to detect Inf correctly. There may be more issues, I've only run one single test out of more than a thousand of tests that we have. I think it just means — don't use -ffast-math for MariaDB. It doesn't work. | |||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2017-05-29 ] | |||||||||||||||||||||||||
|
I don't see what we can do here, sorry. Considering other dtoa implementations — yes, duly noted, thanks. |