Summary: | Very slow execution of sinf function | ||
---|---|---|---|
Product: | glibc | Reporter: | Jerry DeLisle <jvdelisle> |
Component: | math | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | enhancement | CC: | fxcoudert, glibc-bugs, john.wilkinson, rajis, siddhesh |
Priority: | P2 | Flags: | fweimer:
security-
|
Version: | unspecified | ||
Target Milestone: | 2.27 | ||
Host: | x86_64-unknown-linux-gnu | Target: | x86_64-redhat-linux-gnu |
Build: | Last reconfirmed: | ||
Attachments: | here is the log of current 2012/06/21 GLIBC IA32 sinf/cosf errors |
On a openSUSE 11.0alpha3, x86_64, glibc 2.7 (20071106 system, the sinf() calls the ../sysdeps/x86_64/fpu/s_sincosf.c:175 FPU function whereas on a Fedora 8 system with glibc 2.7 the ../sysdeps/ieee754/flt-32/s_sinf.c, line 29 software implementation of sinf is called. Any suggestions on how to fix this. We should be using the FPU calls. I had a similar problem with sin function. The problem is connected only to 64-bit distribution. Using of sinl function is temporary solution, but I had to call it usually this way, because of unwanted optimizations: volatile long double _x = x; // x is argument for the sin function (type double) volatile long double result = sinl(_x); my own bug report (marked as invalid ;-( ) http://sourceware.org/bugzilla/show_bug.cgi?id=5781 I assume that for the 64-bit distribution (x86_64), it should use sin and sinf from i386 arch (sysdeps\i386\fpu\s_sin.S and sysdeps\i386\fpu\s_sinf.S) and only sinl implementation is explicit x86_64. But the sin and sinf are now used as software versions (IBM library). Confirmed with current sources. Given that sinf is not correctly rounding (see bug 1163) it's quite possible there is a reasonable fix that does not involve a whole new correctly rounding implementation - although we're generally moving away from x87 trig instructions as too inaccurate (see bug 13658). Created attachment 6469 [details]
here is the log of current 2012/06/21 GLIBC IA32 sinf/cosf errors
FWIW, the function now runs much faster after the multiple precision improvements. The worst case is only about a 100 times slower now instead of 1000 times. I've not looked yet, but I think there is a case for capping maximum precision for worst case computation for sin (and all trigonometric functions) as well, so this could get even better. *** Bug 16531 has been marked as a duplicate of this bug. *** Fixed by commit 7863a7118112fe502e8020a0db0fa74fef281f29. |
With this test case: #include <stdio.h> #include <math.h> unsigned int ta; main () { double result; for (ta = 1; ta <= 8000000; ta++) { result = sin(ta * 3.14159); } printf("result = \t%.13e\n", result); } Using sin vs sinf. sin: $ time ./a.out result = -6.9068092664138e-01 real 0m0.782s user 0m0.778s sys 0m0.004s sinf: $ time ./a.out result = -6.9068092107773e-01 real 0m8.622s user 0m8.605s sys 0m0.009s The difference in assembly code (-S output): 44,47c44,47 < call sin < movsd %xmm0, -40(%rbp) < movq -40(%rbp), %rax < movq %rax, -8(%rbp) --- > cvtsd2ss %xmm0, %xmm0 > call sinf > cvtss2sd %xmm0, %xmm0 > movsd %xmm0, -8(%rbp) I don't think the conversion functions should account for this huge time difference. Also with -m32 and sinf I get: $ time ./a.out result = -6.9068092664141e-01 real 0m1.157s user 0m0.765s sys 0m0.002s Which is more reasonable. $ gcc -v Using built-in specs. Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=x86_64-redhat-linux Thread model: posix gcc version 4.1.2 20070925 (Red Hat 4.1.2-33) I am running latest Fedora 8 See also gfortran bug pr34128.