Megosztás:


Lebegőpontos migrálási problémák

Néha, amikor a projekteket a Visual Studio újabb verziójára frissíti, bizonyos lebegőpontos műveletek eredményeinek változásait tapasztalhatja. Ez általában két okból történik: kódgenerálási változások, amelyek jobban kihasználják a rendelkezésre álló processzort, valamint a C futtatókörnyezeti kódtár (CRT) matematikai függvényeiben használt algoritmusok hibajavításai vagy módosítása. Általánosságban elmondható, hogy az új eredmények a nyelvi szabvány által meghatározott korlátokon belül helyesek. Olvasson tovább, hogy megtudja, mi változott, és ha fontos, hogyan kaphatja meg ugyanazokat az eredményeket, mint korábban a függvények.

Új matematikai függvények és univerzális CRT-változások

A legtöbb CRT matematikai függvény már évek óta elérhető a Visual Studióban, de a Visual Studio 2013-tól kezdve az ISO C99 által igényelt összes függvény megtalálható benne. Ezek a függvények a teljesítmény és a helyesség egyensúlyának érdekében vannak implementálva. Mivel a helyesen lekerekített eredmény előállítása minden esetben rendkívül költséges lehet, ezek a függvények úgy vannak kialakítva, hogy hatékonyan közelítsenek a helyesen lekerekített eredményhez. A legtöbb esetben a létrehozott eredmény a helyesen lekerekített eredmény +/-1 egységén belül van, amely megegyezik a legkisebb pontosságú (ulp) értékkel. Ugyanakkor lehetnek olyan esetek, amikor nagyobb a hibahatár. Ha korábban más matematikai kódtárat használt ezeknek a függvényeknek a beszerzéséhez, a megvalósítási különbségek magyarázhatják az eredmények változását.

Amikor a matematikai függvényeket áthelyezték a Visual Studio 2015 Universal CRT-be, néhány új algoritmust használtak, és számos hibát kijavítottak a Visual Studio 2013-ban új függvények implementálásában. Ezek a módosítások az ezeket a függvényeket használó lebegőpontos számítások eredményeiben észlelhető különbségeket eredményezhetnek. A hibaproblémákat okozó függvények a következőek voltak: erf, exp2, remainder, remquo, scalbln, és scalbn, valamint azok lebegőpontos és hosszú double változatai. A Visual Studio 2015 egyéb módosításai kijavították a lebegőpontos állapotszó és kivételállapot-információk megőrzésével kapcsolatos problémákat a _clear87, _clearfp, fegetenv, fesetenv és feholdexcept függvényekben.

Processzorkülönbségek és fordítójelzők

A lebegőpontos matematikai kódtár számos függvénye különböző implementációkkal rendelkezik a különböző CPU-architektúrákhoz. A 32 bites x86 CRT például eltérő implementációval rendelkezhet, mint a 64 bites x64 CRT. Emellett egyes függvények több implementációval is rendelkezhetnek egy adott CPU-architektúra esetében. A leghatékonyabb implementációt a processzor által támogatott utasításkészlettől függően dinamikusan választja ki futásidőben. A 32 bites x86 CRT-ben például egyes függvények x87-implementációval és SSE2-implementációval is rendelkeznek. Az SSE2-t támogató cpu-n való futtatás esetén a gyorsabb SSE2 implementációt használja a rendszer. Ha olyan CPU-n fut, amely nem támogatja az SSE2-t, a rendszer a lassabb x87-implementációt használja. Ez a régi kód áttelepítésekor jelenhet meg, mivel az alapértelmezett x86 fordítóarchitektúra-beállítás /arch:SSE2 értékre változott a Visual Studio 2012-ben. Mivel a matematikai kódtárfüggvények különböző implementációi különböző CPU-utasításokat és különböző algoritmusokat használhatnak az eredmények előállításához, a függvények eltérő eredményeket hozhatnak létre különböző platformokon. A legtöbb esetben az eredmények a helyesen lekerekített eredmény +/-1 ulp értékén belül vannak, de a tényleges eredmények processzoronként eltérőek lehetnek.

A különböző lebegőpontos módok kódgenerációs fejlesztései megváltoztathatják a lebegőpontos eredményeket is, amikor a régi kódot az új kódhoz hasonlítják, még azonos fordítójelölőkkel is. Előfordulhat például, hogy amikor a Visual Studio 2010 által generált kód esetén a /fp:pontos (alapértelmezett) vagy /fp:strict van megadva, a köztes nem szám (NaN) értékek nem kerülnek megfelelően továbbításra a kifejezéseken keresztül. Így egyes kifejezések, amelyek numerikus eredményt adtak a régebbi fordítókban, most már helyesen hozhatnak létre NaN-eredményt. Azért is lehetnek különbségek, mert az engedélyezett /fp:fast kódoptimalizálások most kihasználják a további processzorfunkciókat. Ezek az optimalizálások kevesebb utasítást használhatnak, de hatással lehetnek a létrehozott eredményekre, mert néhány korábban látható köztes művelet el lett távolítva.

Azonos eredmények lekérése

A legtöbb esetben a legújabb fordítók és kódtárak lebegőpontos változásai gyorsabb vagy helyesebb működést eredményeznek, vagy mindkettőt. Még jobb processzorteljesítményt is tapasztalhat, ha az SSE2 utasítások lecserélik az x87-utasításokat. Ha azonban olyan kóddal rendelkezik, amelynek pontosan replikálnia kell egy régebbi fordító lebegőpontos viselkedését, fontolja meg a Visual Studio natív, több célzási funkciójának használatát. Az érintett projektet építse a régebbi buildeszközökkel. További információ: A Visual Studióban natív többcélú célzás használata régi projektekkészítéséhez.

Lásd még

Projektek frissítése a Visual C++ korábbi verzióiról
A lehetséges frissítési problémák áttekintése (Visual C++)
Visual C++ változáselőzmények 2003 – 2015