Pytanie g ++ opcje optymalizacji wpływają na wartość funkcji grzechu


Mam problem z funkcją "grzechu" libc.

#include <cmath>
#include <stdio.h>

int main(int argc, char **argv)
{
    double tt = 6.28318530717958620000; // 2 * M_PI
    double yy = ::sin(tt);

    printf("%.32f\n", yy);

    return 0;
}

Gdy skompilujesz powyższy kod używając "g ++" bez opcji optymalizacji, wyświetli "-0.00000000000000024492127076447545". Ale jeśli z opcją "-O3", wyświetli "-0.00000000000000024492935982947064".

Dlaczego nie zwraca "-0.00000000000000024492935982947064" bez "-O3"? Z góry dziękuję.


12
2018-02-12 14:26


pochodzenie


Czy mogę wiedzieć, która wersja g ++ i jakiego systemu operacyjnego i sprzętu używasz? - Viet
g ++ 4.4.3, ubuntu 10.04 i Intel (R) Core ™ i3-2310M CPU @ 2.10GHz. DZIĘKI. - Shen Weizheng
Sprawdź -ffast-math opcja być może. - Kerrek SB
-Ofast Warto tu także wspomnieć. - Niklas R
-ffast-matma nie ma wpływu na wynik. -Ofast nie jest prawidłowym argumentem opcji g ++. - Shen Weizheng


Odpowiedzi:


Ponieważ przy "-O3" kompilator wykonuje wstępne obliczenia sin(2*pi) w czasie kompilacji, z jednym algorytmem. Bez "-O3" jest to obliczane w czasie wykonywania, z innym algorytmem.

Może tak być, ponieważ sam kompilator został zbudowany z pewną biblioteką matematyczną, która różni się od twojej biblioteki matematycznej.

Aktualizacja

Jedyną jednostką dającą wynik "-0.00000000000000024492127076447545" jest 32-bitowa wersja libstdc ++. Wersja 64-bitowa tej samej biblioteki oraz sama gcc produkuje "-0.00000000000000024492935982947064".

Tak więc uaktualnienie do nowszej wersji nie pomoże. Próbowałem także różnych opcji, proponowanych tutaj: ani -ffloat-store, ani -fno-builtin nie robi żadnej różnicy, a także długie podwójne i sinl.

32-bitowy libstdc ++ używa 387 instrukcji zmiennoprzecinkowych, podczas gdy gcc najwyraźniej używa instrukcji SSE. Oto różnica. Prawdopodobnie jedynym sposobem na ich spójność jest przebudowanie gcc ze źródeł, kierując go tylko wewnętrznie do 387 instrukcji.


6
2018-02-12 14:50



Dzięki za odpowiedź. Czy wiesz, czy możliwe jest uzyskanie "-0.00000000000000024492935982947064" w czasie wykonywania? I jak? - Shen Weizheng
@Sanders -fno-builtin aby upewnić się, że nie jest używana wbudowana funkcja, zwykle pomaga uniknąć wyniku, który zostanie obliczony podczas kompilacji. Jednak wynik, jaki otrzymujesz, nie jest normalny, prawdopodobnie istnieje błąd w kompilatorze lub w bibliotece. Powinieneś spróbować zaktualizować do nowej wersji. - ouah
@ouah OK, zaktualizuję moją wersję g ++ i spróbuję. DZIĘKI. - Shen Weizheng
Mój gcc 4.6.1 we wszystkich przypadkach daje -0.00000000000000024492935982947064, więc jeśli uaktualnisz do tej wersji lub do najnowszej wersji (zarówno kompilatora, jak i bibliotek), uzyskasz spójny wynik. Możesz także spróbować zaktualizować je do domyślnych wersji swojej dystrybucji Ubuntu. Lub ponownie skompilować gcc ze źródeł. - Evgeny Kluev
Nie sądzę, że to jest właściwa odpowiedź. - Maxim Egorushkin