Sdílet prostřednictvím


Problémy migrace s plovoucí desetinnou čárkou

Při upgradu projektů na novější verzi Visual Studio si můžete všimnout změn ve výsledcích určitých operací s pohyblivou řádovou čárkou. K tomu obvykle dochází z jednoho ze dvou důvodů: změny generování kódu, které využívají lepší výhodu dostupného procesoru, a opravy chyb nebo změny algoritmů používaných v matematických funkcích v knihovně modulu runtime jazyka C (CRT). Obecně platí, že nové výsledky jsou správné v mezích stanovených jazykem standardu. Přečtěte si, jak zjistit, co se změnilo, a pokud je důležité, jak získat stejné výsledky, které funkce získaly dříve.

Nové matematické funkce a změny Univerzální CRT

Většina matematických funkcí CRT je v sadě Visual Studio k dispozici už několik let, ale počínaje sadou Visual Studio 2013 jsou zahrnuty všechny funkce vyžadované iso C99. Tyto funkce se implementují pro vyvážení výkonu s správností. Vzhledem k tomu, že vytvoření správně zaokrouhleného výsledku může být v každém případě příliš nákladné, jsou tyto funkce navrženy tak, aby efektivně vytvářely blízkou aproximaci správně zaokrouhleného výsledku. Ve většině případů je výsledek v rozsahu +/-1 jednotky nejnižší přesnosti nebo ulp správně zaokrouhleného výsledku, i když může nastávat větší nepřesnost. Pokud jste k získání těchto funkcí použili jinou matematickou knihovnu, můžou rozdíly v implementaci vysvětlit změnu ve výsledcích.

Když byly matematické funkce přesunuty do Univerzální CRT v sadě Visual Studio 2015, byly použity některé nové algoritmy a několik chyb v implementaci funkcí, které byly v sadě Visual Studio 2013 nové. Tyto změny můžou vést k zjistitelným rozdílům ve výsledcích výpočtů s plovoucí desetinnou čárkou, které tyto funkce používají. Funkce, které měly chyby, byly erf, exp2, remainder, remquo, scalbln, a scalbn, a jejich varianty float a long double. Další změny ve Visual Studio 2015 opravily problémy se zachováním stavového kódu s plovoucí desetinnou čárkou a informací o stavu výjimky ve funkcích _clear87, _clearfp, fegetenv, fesetenv a feholdexcept.

Rozdíly procesoru a příznaky kompilátoru

Mnoho funkcí matematické knihovny s plovoucí desetinou čárkou má různé implementace pro různé architektury procesoru. Například 32bitová verze x86 CRT může mít jinou implementaci než 64bitová verze x64 CRT. Některé funkce navíc můžou mít několik implementací pro danou architekturu procesoru. Nejúčinnější implementace je vybrána dynamicky za běhu v závislosti na sadách instrukcí podporovaných procesorem. Například v 32bitovém x86 CRT mají některé funkce implementaci x87 i implementaci SSE2. Při spouštění na procesoru, který podporuje SSE2, se použije rychlejší implementace SSE2. Při spouštění na procesoru, který nepodporuje SSE2, se používá pomalejší implementace x87. Může se zobrazit při migraci starého kódu, protože výchozí možnost architektury kompilátoru x86 se v sadě Visual Studio 2012 změnila na /arch:SSE2 . Vzhledem k tomu, že různé implementace funkcí matematické knihovny mohou k vytvoření výsledků používat různé instrukce procesoru a různé algoritmy, mohou funkce vytvářet různé výsledky na různých platformách. Ve většiněpřípadůch

Vylepšení generování kódu v různých metodách s plovoucí řádovou čárkou mohou také měnit výsledky s plovoucí řádovou čárkou při porovnávání starého kódu s novým kódem, a to i se stejnými nastaveními kompilátoru. Například kód, který vygeneruje Visual Studio 2010, pokud je specifikována možnost /fp:precise (výchozí) nebo /fp:strict, nemusí správně propagovat mezilehlé hodnoty NaN v rámci výrazů. Některé výrazy, které daly číselný výsledek ve starších kompilátorech, teď mohou správně vytvořit výsledek NaN. Můžete se také setkat s rozdíly, protože optimalizace kódu povolené pro /fp:fast tuto chvíli využívají více funkcí procesoru. Tyto optimalizace můžou používat méně instrukcí, ale můžou ovlivnit vygenerované výsledky, protože některé dříve viditelné přechodné operace byly odebrány.

Jak získat identické výsledky

Ve většině případů změny s plovoucí desetinou čárkou v nejnovějších kompilátorech a knihovnách vedou k rychlejšímu nebo přesnějšímu chování nebo obojímu. Pokud instrukce SSE2 nahrazují instrukce x87, můžete dokonce vidět lepší výkon procesoru. Pokud ale máte kód, který musí přesně replikovat chování staršího kompilátoru s plovoucí desetinnou čárkou, zvažte použití nativní funkce vícenásobného cílení Visual Studio a sestavte daný projekt staršími nástroji pro sestavení. Další informace najdete v tématu Použití nativního cílení na více verzí v sadě Visual Studio k sestavení starých projektů.

Viz také

Upgrade projektů ze starších verzí jazyka Visual C++
Přehled potenciálních problémů s upgradem (Visual C++)
Historie změn Visual C++ 2003–2015