Основният проблем с този код за пренасяне към x64 е, че той използва грешна единица с плаваща запетая. На x64 плаващата запетая се извършва на модула SSE.
Да, x87 модулът все още е там, но е бавен в сравнение. Друг проблем е, че x64 ABI предполага, че ще използвате SSE модула. Параметрите пристигат в регистрите на SSE. Стойностите с плаваща запетая се връщат в SSE регистър. Безсмислено е (да не говорим за доста упорита работа и отнема много време) да се прехвърлят стойности между SSE и x87 единици. Нещо повече, управлението с плаваща запетая, маските за изключения се инициализират за SSE единицата, но сигурни ли сте, че ще бъдат правилно зададени за SSE единицата.
Така че, с оглед на всичко това, горещо ви съветвам да се уверите, че целият ви код с плаваща запетая се изпълнява на модула SSE под x64. Мисля, че единственият случай, когато може да се направи случай за използване на регистъра x87, е за алгоритъм, който изисква 10-байтов разширен тип, който се поддържа от x87, но не и от SSE. Тук не е така.
Сега, пренасянето към SSE модула не е толкова просто, колкото превеждането на кодовете за операции в SSE еквиваленти. Това е така, защото плаващият модул на SSE има много по-малко вградени възможности. Например, няма тригонометрични функции, включени в SSE кодовете за операции.
Така че правилният начин да се справите с това е да преминете към използване на Pascal код. Тези функции могат да бъдат заменени с Math.ArcTan2
и Math.ArcSin
съответно.
За да разберем това по-подробно, нека да разгледаме какво е включено в извършването на изчисленията на x87 единица, под x64. Кодът за ArcSin
изглежда така:
function ArcSin(X: Double): Double;
// to be 100% clear, do **not** use this code
asm
movq [rsp-8], xmm0 // X arrives in xmm0, move it to stack memory
fld qword ptr [rsp-8] // now load X into the x87 unit
fld st(0) // calculation code exactly as before
fmul st(0), st(0)
fld1
fsubrp st(1), st(0)
fsqrt
fpatan
fwait
fstp qword ptr [rsp-8] // but now we need to move the return value
movq xmm0, [rsp-8] // back into xmm0, again via the stack
end;
Точки за отбелязване:
- x64 ABI означава, че входният параметър пристига в xmm0. Не можем да го заредим директно в модула x87. Така че трябва да прехвърлим от xmm0, за да изтрием паметта в стека и след това да заредим от там в модула x87.
- И ние трябва да направим подобно, когато връщаме стойността. Стойността се връща в xmm0, както е посочено от ABI. Така че трябва да излезем от модула x87, да изтрием паметта на стека и след това да заредим в xmm0.
- Напълно пренебрегнахме контролната дума с плаваща запетая: маскиране на изключение, контрол на прецизност и закръгляне и т.н. Ако трябваше да направите това, трябва да съберете механизъм, който да гарантира, че контролната дума на x87 модула се обработва по разумен начин.
Така че може би това може да послужи като предупреждение за бъдещи посетители, които желаят да използват x87 за извършване на аритметика с плаваща запетая под x64.
person
David Heffernan
schedule
24.12.2013
Math.ArcSin
иMath.ArcTan
. - person LU RD   schedule 24.12.2013Math.ArcTan2
то би трябвало. Изобщо не използвайте asm. - person LU RD   schedule 24.12.2013FWAIT
код на операцията след всеки израз. - person Arioch 'The   schedule 25.12.2013Трябва да обработя заявката асинхронно във времето - след получаване на заявка трябва да върна отговор със статус 200, за да потвърдя, че заявката е достигнала целта си, и след това да продължа с някаква магия, която да се случи в услугата. Опитах няколко начина да го достигна, но всеки път отговорът беше изпратен, след като логическата част завърши в друга нишка.
Има ли начин да го достигнете с помощта на Spring? Или трябва да помисля за друг подход към този проблем?
- person Arioch 'The   schedule 25.12.2013