Problémy migrace s plovoucí desetinnou čárkou

Někdy při upgradu projektů na novější verzi sady Visual Studio můžete zjistit, že se změnily výsledky určitých operací s plovoucí desetinou čá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 s nejnižší přesností nebo lpem správně zaokrouhleného výsledku, i když mohou existovat případy, kdy je větší nepřesnost. Pokud jste k získání těchto funkcí dříve používali jinou matematickou knihovnu, můžou za změnu ve výsledcích odpovídat rozdíly v implementaci.

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, u kterých došlo k problémům s chybami, byly erf, exp2, zbytek, remquo, scalbln a scalbn a jejich float a dlouhé dvojité varianty. Další změny v sadě Visual Studio 2015 opravily problémy při zachování informací o stavu s plovoucí desetinou čárkou a stavu výjimek v _clear87, _clearfp, fegetenv, fesetenv a funkcích 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í správnosti generování kódu v různých režimech s plovoucí desetinnou čárkou v sadě Visual Studio můžou také ovlivnit výsledky operací s plovoucí desetinnou čárkou, když se starý kód porovná s novým kódem, i když používáte stejné příznaky kompilátoru. Například kód vygenerovaný sadou Visual Studio 2010, když /fp:precise (výchozí) nebo /fp:strict byl zadán, nemusí správně rozšířit mezilehlé hodnoty nečíslo (NaN) prostřednictvím 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í desetinou čárkou, zvažte použití nativních funkcí více cílení sady Visual Studio a sestavte ovlivněný projekt se starší sadou nástrojů. 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