التقييم التلقائي على مزدوج و ffast-math
-
27-09-2019 - |
سؤال
لماذا هو إلزامي للاستخدام -ffast-math
مع G ++ لتحقيق ضبط الحلقات باستخدام double
س؟ أنا لا أحب -ffast-math
لأنني لا أريد أن أفقد الدقة.
المحلول
أنت لا تفقد الدقة بالضرورة -ffast-math
. يؤثر فقط على التعامل مع NaN
, Inf
وما إلى ذلك والترتيب الذي يتم فيه تنفيذ العمليات.
إذا كان لديك جزء معين من التعليمات البرمجية حيث لا تريد إعادة ترتيب GCC أو تبسيط الحسابات ، فيمكنك وضع علامة على المتغيرات على أنها تستخدم باستخدام ملف asm
بيان.
على سبيل المثال ، يقوم الرمز التالي بإجراء عملية التقريب f
. ومع ذلك ، الاثنين f += g
و f -= g
من المحتمل أن تحصل العمليات على تحسينها بواسطة GCC:
static double moo(double f, double g)
{
g *= 4503599627370496.0; // 2 ** 52
f += g;
f -= g;
return f;
}
على x86_64 ، يمكنك استخدام هذا asm
بيان لإرشاد GCC بعدم إجراء هذا التحسين:
static double moo(double f, double g)
{
g *= 4503599627370496.0; // 2 ** 52
f += g;
__asm__("" : "+x" (f));
f -= g;
return f;
}
ستحتاج إلى تكييف هذا لكل بنية ، لسوء الحظ. على PowerPC ، استخدم +f
بدلاً من +x
.
نصائح أخرى
من المحتمل جدًا لأن التقييم يعني أنه قد يكون لديك نتائج مختلفة ، أو قد تعني أنك تفوت إشارات/استثناءات النقطة العائمة.
إذا كنت تقوم بتجميع 32 بت X86 ، فستكون GCC و G ++ افتراضيًا لاستخدام X87 للرياضيات العائمة ، في 64 بت ، فهي افتراضية لـ SSE ، ومع ذلك ، يمكن لـ X87 أن تنتج قيمًا مختلفة لنفس الحساب بحيث يكون من غير المحتمل G ++ سوف تفكر في التفكير إذا كان لا يمكن أن تضمن أنك ستحصل على نفس النتائج ما لم تستخدم -ffast-math
أو بعض الأعلام التي يتم تشغيلها.
في الأساس ، قد لا يكون الأمر يتعلق ببيئة النقطة العائمة للرمز المتجهي
-fno-math-errno -fno-trapping-math -fno-signaling-nans -fno-rounding-math
لكن ابحث أولاً عن تلك الخيارات وتأكد من أنها لن تؤثر على صحة البرنامج. -ffinite-math-only
قد تساعد أيضا
لان -ffast-math
تمكين المعاملات إعادة ترتيب الذي يسمح للعديد من التعليمات البرمجية أن تكون متجه.
على سبيل المثال لحساب هذا
sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + … a[99]
المترجم هو مطلوب للقيام بالإضافات بالتتابع بدون -ffast-math
, ، لأن الرياضيات النقطة العائمة ليست مبتدرة ولا ترابطية.
- هل النقطة العائمة إضافة التبادلية وترابطية؟
- هل إضافة النقطة العائمة التبادلية في C ++؟
- هل عمليات النقطة العائمة في Cترافسة؟
- هل إضافة النقطة العائمة والضرب الترابطية؟
هذا هو نفس السبب لماذا لا يمكن للمترجمين تحسين a*a*a*a*a*a
إلى (a*a*a)*(a*a*a)
بدون -ffast-math
هذا يعني أنه لا يوجد تخصيص متاح إلا إذا كان لديك ناقل أفقي فعال للغاية يضيف.
ومع ذلك، إذا -ffast-math
تم تمكينه ، يمكن حساب التعبير مثله (ينظر الى A7. Auto-Vectorization
)
sum0 = a[0] + a[4] + a[ 8] + … a[96]
sum1 = a[1] + a[5] + a[ 9] + … a[97]
sum2 = a[2] + a[6] + a[10] + … a[98]
sum3 = a[3] + a[7] + a[11] + … a[99]
sum’ = sum0 + sum1 + sum2 + sum3
الآن يمكن للمترجم أن يتجه بسهولة عن طريق إضافة كل عمود بالتوازي ثم قم بإضافة أفقي في النهاية
يفعل
sum’ == sum
؟ فقط اذا(a[0]+a[4]+…) + (a[1]+a[5]+…) + (a[2]+a[6]+…) + ([a[3]+a[7]+…) == a[0] + a[1] + a[2] + …
هذا ينطبق تحت الارتباط ، الذي لا يطفو ، طوال الوقت. تحديد/fp:fast
دع المترجم يحول الكود الخاص بك ليتم تشغيله بشكل أسرع - ما يصل إلى 4 مرات أسرع ، لهذا الحساب البسيط.هل تفضل بسرعة أم دقيقة؟ - A7. تلقائي التلقائي
قد يتم تمكينه بواسطة -fassociative-math
العلم في مجلس التعاون الخليجي