سؤال

أواجه مشكلة غريبة حقيقية باستخدام GCC للذراع مع تشغيل التحسينات. يؤدي تجميع تطبيق C ++ الخاص بي دون التحسينات إلى تنفيذها في وقت التشغيل يخرج النتائج المتوقعة في وقت التشغيل. بمجرد تشغيل التحسينات - أي -o1 - فشل طلبي في تحقيق النتائج المتوقعة. حاولت لبضعة أيام اكتشاف المشكلة ولكني جاهل. لقد ألغت أي متغيرات غير ضائعة من الكود الخاص بي ، لقد قمت بتصحيح البقع التي يمكن أن يسبب فيها التعرج الصارم مشاكل ولكن لا يزال ليس لدي النتائج المناسبة.

أنا أستخدم GCC 4.2.0 لـ ARM (المعالج هو ARM926EJ-S) وتشغيل التطبيق على توزيع Montavista Linux.

فيما يلي الأعلام التي أستخدمها:

-O1 -fno-unroll-loops fno-merge-constants -fno-omit-frame-pointer -fno-toplevel-reorder \
-fno-defer-pop -fno-function-cse -Wuninitialized -Wstrict-aliasing=3 -Wstrict-overflow=3 \
-fsigned-char -march=armv5te -mtune=arm926ej-s -ffast-math

بمجرد أن أقوم بتجريد علامة -o1 وأعد ترجمة/إعادة توليد التطبيق ، أحصل على نتائج الإخراج المناسبة. كما ترون من الأعلام حاولت تعطيل أي تحسين اعتقدت أنه قد يسبب مشاكل ولكن لا حظ.

هل لدى أي شخص أي مؤشرات حول كيف يمكنني معالجة هذه المشكلة؟

شكرًا

هل كانت مفيدة؟

المحلول

بشكل عام ، إذا قلت "التحسين يكسر برنامجي" ، فهو 99.9 ٪ برنامج هذا مكسور. تمكين التحسينات فقط يكتشف الأخطاء في الكود الخاص بك.

يجب أن تسير بسهولة في خيارات التحسين. فقط في ظروف محددة للغاية ستحتاج إلى أي شيء آخر يتجاوز الخيارات القياسية -o0 و -o2 و -o3 وربما -OS. إذا كنت تشعر بك فعل بحاجة إلى إعدادات أكثر تحديدًا من ذلك ، استجيبت تعويذة التحسينات:

القياس ، تحسين ، القياس.

أبداً اذهب من خلال "شعور الأمعاء" هنا. أثبت أن خيار التحسين غير القياسي معين لا يفيد تطبيقك بشكل كبير ، وفهم لماذا (أي ، فهم بالضبط ما يفعله هذا الخيار ، ولماذا يؤثر على الكود الخاص بك).

هذا ليس مكانًا جيدًا للتنقل معصوب العينين.

ورؤية كيفية استخدام الخيار الدفاعي (-o1) ، ثم تعطيل نصف دزينة من التحسينات ، و ومن بعد أضف -fast -math ، يقودني إلى افتراض أنك تفعل ذلك حاليًا.

حسنا ، ربما العين واحدة.

ولكن خلاصة القول هي: إذا كان التمكين تحسين الرمز الخاص بك ، فمن المحتمل أن يكون خطأ الكود الخاص بك.

تعديل: لقد وجدت هذا للتو في دليل دول مجلس التعاون الخليجي:

-ffast-math: لا ينبغي أبدًا تشغيل هذا الخيار بواسطة أي خيار -o لأنه يمكن أن يؤدي إلى إخراج غير صحيح للبرامج التي تعتمد على تنفيذ دقيق لقواعد/مواصفات ISO لوظائف الرياضيات.

هذا يقول ، في الأساس ، الخاص بك -O1 -ffast-math يمكن أن تنكسر بالفعل صحيح الشفرة. ومع ذلك ، حتى لو كان يأخذ -ffast-math يزيل مشكلتك الحالية ، يجب أن يكون لديك على الأقل فكرة لماذا. وإلا فقد تتبادل مشكلتك فقط حاليا مع مشكلة في لحظة أكثر إزعاجا في وقت لاحق (مثل ، عندما ينكسر منتجك في موقع عميلك). هل هو حقا -ffast-math كانت هذه هي المشكلة ، أو هل كسرت رمز الرياضيات كشف بواسطة -ffast-math?

نصائح أخرى

-ffast-math يجب تجنبها إن أمكن. فقط استخدم -O1 في الوقت الحالي وإسقاط جميع مفاتيح التحسين الأخرى. إذا كنت لا تزال ترى مشاكل ، فقد حان الوقت لبدء تصحيح الأخطاء.

دون رؤية التعليمات البرمجية الخاصة بك ، من الصعب أن تصبح أكثر تحديدًا من "ربما لديك خطأ".

هناك سيناريوهان حيث يغير تحسين التحسينات دلالات البرنامج:

  • يوجد خطأ في المترجم ، أو
  • هناك خطأ في الكود الخاص بك.

هذا الأخير هو على الأرجح. على وجه التحديد ، ربما تعتمد على السلوك غير المحدد في مكان ما في البرنامج. أنت تعتمد على شيء ما يحدث أن يكون صحيحًا عند التجميع هذه المترجم على هذه الكمبيوتر مع هؤلاء أعلام المترجم ، ولكنها ليست مضمونة باللغة. وهكذا ، عند تمكين التحسينات ، فإن GCC ليس ملزماً بالحفاظ على هذا السلوك.

أظهر لنا الرمز الخاص بك. أو تخطوها في مصحح الأخطاء حتى تصل إلى النقطة التي تسوء فيها الأمور.

لا يمكنني أن أكون أكثر تحديدًا. قد يكون مؤشرًا متدليًا ، أو متغيرات غير مؤهلة ، أو كسر قواعد التعرجات ، أو حتى مجرد القيام بأحد الأشياء العديدة التي تسفر عن نتائج غير محددة (مثل i = i++)

حاول إجراء الحد الأدنى من قضية الاختبار. أعد كتابة البرنامج ، وإزالة الأشياء التي لا تؤثر على الخطأ. من المحتمل أن تكتشف الخطأ بنفسك في هذه العملية ، ولكن إذا لم تفعل ذلك ، فيجب أن يكون لديك برنامج مثال واحد على الشاشة يستطيع بريد.

صدفة، إذا, ، كما تكهن آخرون ، هو كذلك -ffast-math الذي يسبب مشكلتك (أي التجميع مع فقط -O1 يعمل بشكل جيد) ، فمن المحتمل أن يكون لديك بعض الرياضيات هناك يجب إعادة كتابة على أي حال. إنه قليلاً من التبسيط ، ولكن -ffast-math يسمح للمترجم بإعادة ترتيب الحسابات بشكل أساسي حيث يمكنك تجريد الأرقام الرياضية - على الرغم من أن القيام بذلك على الأجهزة الحقيقية قد يتسبب في نتائج مختلفة قليلاً لأن أرقام النقاط العائمة ليست دقيقة. من المحتمل أن يكون الاعتماد على هذا النوع من التفاصيل العائمة غير المقصود.

إذا كنت تريد فهم الخطأ ، فإن الحد الأدنى من حالة الاختبار أمر بالغ الأهمية في أي حال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top