Piszę w czasie rzeczywistym oprogramowanie numeryczne, w C++, obecnie kompilując je z Visual-C++ 2008. Teraz używając "szybkiego" modelu zmiennoprzecinkowego (/fp:fast
), różne optymalizacje większość z nich użyteczne moja sprawa, ale konkretnie:Pływające opcje kompilatora C++ | Zapobieganie a/b -> a * (1/b)
a/b -> a*(1/b) Division by multiplicative inverse
jest zbyt niestabilne numerycznie do-wielu moich obliczeń.
(patrz: Microsoft Visual C++ Floating-Point Optimization)
Przełączanie /fp:precise
sprawia, że moja aplikacja uruchomić więcej niż dwa razy powoli. Czy możliwe jest precyzyjne dostrojenie optymalizatora (tj. Wyłączenie tej konkretnej optymalizacji), lub w jakiś sposób ręcznie ominąć go?
- rzeczywisty przykład minimalny Kod: -
void test(float a, float b, float c,
float &ret0, float &ret1) {
ret0 = b/a;
ret1 = c/a;
}
[My rzeczywisty kod jest najczęściej związane z macierzą algorytmy]
wyjściowy VC (Cl, wersja 15 0x86) wynosi:
divss xmm0,xmm1
mulss xmm2,xmm0
mulss xmm1,xmm0
Posiadanie jednego diva, zamiast dwóch, jest dużym problemem numerycznym, (xmm0, jest wstępnie załadowany z 1.0f z pamięci RAM), zależnie od wartości xmm1,2 (które mogą być w różnych r anges) możesz stracić dużo precyzji (Kompilacja bez SSE, daje podobny kod stack-x87-FPU).
Owijanie funkcję z
#pragma float_control(precise, on, push)
...
#pragma float_control(pop)
nie rozwiązuje problem dokładności, ale po pierwsze, jest ona dostępna tylko w funkcji poziomu (global-zakres), a po drugie, zapobiega inline funkcji (tj kary prędkości są zbyt wysokie)
„precyzyjny” wyjście jest rzutowane na „podwójne” tam iz powrotem jak-dobrze:
divsd xmm1,xmm2
cvtsd2ss xmm1,xmm1
divsd xmm1,xmm0
cvtpd2ps xmm0,xmm1
Każda zmiennoprzecinkowa matematyka, która opiera się na równości, będzie niestabilna. –
@Hans: OP nie szuka równości; on/ona mówi, że kompilator dokonuje powyższej zmiany jako optymalizacji i że jest to nieprzydatne w jego/jej aplikacji. –
@Oli: wciąż nie wiemy, czy wymagania dokładności OP są osiągalne, czy nie z tego świata. – peterchen