لماذا المزيد من تعليمات تجميع بنتيوم يستغرق وقتا أقل؟

StackOverflow https://stackoverflow.com/questions/1099225

  •  11-09-2019
  •  | 
  •  

سؤال

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

النتائج التي نحصل عليها على اثنين من آلات إنتل مختلفة جدا.

تخبر تعليمات CPUID الأسرة والنموذج والتطوير.

الآلة 1: الأسرة 6، نموذج 15 خطوة 11. CPUZ تقارير "Intel Core 2 Duo E6750"
التعليمات تنفذ عند إحصائيا بنفس السرعة.

الآلة 2: الأسرة 15، نموذج 3، خطوة 3. تقارير CPUZ "Intel Pentium 4"
يستغرق التسلسل الأول حوالي 8٪ أطول من التسلسل الثاني.

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

هل لدى أي شخص فكرة لماذا تستغرق التسلسل الأول وقتا أطول للتنفيذ على جهاز واحد؟

تحرير: إضافة "XOR PTR EREG، 0" إلى التسلسل الأول يجعل توقيت تتطابق مع المرتبة الثانية على بنتيوم 4. فضولي.

التسلسل الأول:

00000040               ALUSHIFT_AND_C_V_E LABEL NEAR
00000040  0F B7 04 55       MOVZX   EAX, gwr[(SIZEOF WORD) * EDX]       ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
   00000000 E
00000048  0F B7 14 4D       MOVZX   EDX, gwr[(SIZEOF WORD) * ECX]       ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
   00000000 E
00000050  23 C2             AND     EAX, EDX                            ; AX = L&R      (result)
00000052  A3 00000000 E     MOV     dvalue, EAX                         ; Save the temporary ALU/Shifter result
00000057  C3                RET                                         ; Return

التسلسل الثاني:

00000060               ALUSHIFT_AND_C_V_NE LABEL NEAR
00000060  0F B7 04 55       MOVZX   EAX, gwr[(SIZEOF WORD) * EDX]       ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
   00000000 E
00000068  0F B7 14 4D       MOVZX   EDX, gwr[(SIZEOF WORD) * ECX]       ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
   00000000 E
00000070  23 C2             AND     EAX, EDX                            ; AX = L&R      (result)
00000072  80 35 00000000 E  XOR     BYTE PTR ereg, 1                    ; E = ~E
   01
00000079  A3 00000000 E     MOV     dvalue, EAX                         ; Save the temporary ALU/Shifter result
0000007E  C3                RET                                         ; Return
هل كانت مفيدة؟

المحلول

بعد Pentium I أو II، معظم التحسينات التي يؤديها المحول البرمجي، لم تكن كذلك كما من الضروري. سوف تحلل الرقاقة هذه التعليمات في مايكرو OPS ثم تحسين لك. يمكن أن يكون T فروق التنبؤ الفرعي بين الرقائق أو حقيقة أن XOR + RET مكلفة تماما مثل Ret عادي. أنا لست على دراية نماذج Pentiums التي تنظر إليها أعلاه قولها. احتمال آخر هو أنه يمكن أن يكون أيضا مشكلة مخزئة التخزين المؤقت أو فرق الأجهزة.

قد يكون هناك شيء في مستندات Intel أو قد لا يحدث.

بغض النظر. يعرف مبردون الجمعيون ذوي الخبرة أن الحقيقة الوحيدة تتحقق عن طريق الاختبار، وهو ما تفعله.

نصائح أخرى

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

شكرا لجميع الذين أخذوا الوقت للتحقيق في هذا أو إلقاء نظرة عليه.

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

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

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

قبل بضعة أشهر، كان لدي شيء مماثل يحدث لي. يحتوي مشروعي على مفتاح التبديل لتمكين استخدام __thread لمتغيرات الخيط المحلي. بدونها، سوف تستخدم pthread_getspecific ويحب. هذا الأخير يفعل كل شيء بقدر __thread الإصدار بالإضافة إلى وظيفة الدالة بالإضافة إلى بعض الإرشادات الإضافية لإعداد الوسائط وحفظ السجلات وما إلى ذلك. ومن المثير للاهتمام، أن النسخة الأكثر شاقة كانت أسرع باستمرار. فقط على بنتيوم 4، رغم ذلك. جميع رقائق أخرى تصرفت سلافية.

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