التحسين الابتدائي
عندما يتعلق الأمر بالتحسين، يرفض العديد من الأشخاص ذلك، "سرعات الكمبيوتر سريعة جدًا الآن، ما الفائدة من أن تكون أسرع بنسبة قليلة في المائة؟" هذا منطقي إلى حد ما، حيث تم تحسين النتائج التي تم تجميعها بواسطة المترجمين الحاليين بالكامل، وباستثناء تطوير برامج معينة مثل الرسومات والصور والوسائط المتعددة، فإن التحسين المتعمد ليس ضروريًا في معظم الحالات، ولكن إذا كان المطورون يكتبون التعليمات البرمجية في ذلك. بمرور الوقت، كان لديك بالفعل وعي بالتحسين، أثناء إكمال التحسين، يمكنك ضمان كفاءة التطوير أو حتى تحسينها.
بالطبع، تصميم الخوارزمية هو جوهر التحسين. في معظم الحالات، يتم تحديد كفاءة تنفيذ البرنامج بشكل أساسي من خلال فهم المطور الشامل للبرنامج، وتصميم الخوارزمية، وما إلى ذلك! لكن في بعض الأحيان يكون تحسين التفاصيل أمرًا منطقيًا أيضًا!
علاوة على ذلك، في كثير من الحالات، لا يتطلب هذا النوع من التحسين كتابة التعليمات البرمجية مباشرة من خلال التجميع، ولكن في هذه الحالة يمكن أن يعكس أيضًا تفوق إتقان معرفة التجميع!
مثل الوظيفتين التاليتين:
وظيفة GetBit(i: Cardinal; n: Cardinal): Boolean;
يبدأ
النتيجة := Boolean((i shr n) and 1);
نهاية؛
وظيفة GetBit(i: Cardinal; n: Cardinal): Boolean;
يبدأ
النتيجة := Boolean((1 shl n) and i);
نهاية؛
رمز التجميع المقابل:
موف إي سي إكس، إيديكس
شر إكس، كل
و إياكس، 01 دولارًا
موف إي سي إكس، إيديكس
موف إي دي إكس، 01 دولارًا
إس إتش إل إي دي إكس، سي إل
وإي إكس، إي دي إكس
لديهم نفس الوظيفة، جميعهم يأخذون قيمة جزء معين من i، ويعيدون True إذا كان 1، وخطأ إذا كان 0!
ظاهريًا، قد تعتقد أن كفاءة تنفيذ الوظيفتين هي نفسها، ولكن في الواقع هناك اختلاف. يتم تنفيذ عملية التحويل للبرنامج الأول وفقًا لاتفاقية الاتصال الافتراضية في دلفي، قم بالتسجيل. في هذا الوقت، يتم تخزين القيمة في السجل EAX، ويمكن إكمال عملية التحول مباشرة، ولكن البرنامج الثاني مختلف لإكمال عملية التحول على القيمة الفورية 1، يجب نقله إلى السجل أولاً. لذلك يجب أن يكون هناك تعليمات أخرى! بالطبع، ليس في جميع الحالات، ستكون التعليمات الأقل أسرع من التعليمات الأكثر، أثناء التنفيذ المحدد، يجب علينا أيضًا مراعاة مشكلات مثل دورة الساعة لتنفيذ التعليمات وإقران التعليمات (المزيد حول هذا لاحقًا). المشكلة بشكل مستقل فقط عندما لا يمكن إجراء المقارنات إلا في بيئات تعليمات برمجية محددة.
في ظل الظروف العادية، يكون هذا الاختلاف في الكفاءة ضئيلًا للغاية، ولكن ليس من السيئ أبدًا الحفاظ على الوعي بالتحسين أثناء البرمجة! إذا كان هذا الكود موجودًا في الطبقة الأعمق للحلقة، وتراكمت دورات الساعة N من خلال عدد كبير من الحلقات، فقد يصبح الفرق في كفاءة التنفيذ كبيرًا جدًا!
ما ورد أعلاه مجرد مثال صغير، ويمكن ملاحظة أنه إذا كنت تستطيع التفكير في بعض المشكلات من منظور التجميع أثناء التطوير، فيمكنك كتابة تعليمات برمجية مفصلة أكثر كفاءة بلغات عالية المستوى مع ضمان كفاءة التطوير! ولكن لا يزال هناك عدة مرات يجب فيها إكمال التحسين التفصيلي باستخدام رمز التجميع المضمن، وفي بعض الأحيان بسبب تطبيق رمز التجميع المضمن، يمكن أيضًا أن تصبح كتابة التعليمات البرمجية أكثر كفاءة.
إذا كنت بحاجة إلى عكس ترتيب البايت لرقم مكون من 32 رقمًا، فكيف يمكنك القيام بذلك بالكامل بلغة عالية المستوى في دلفي؟ يمكنك استخدام التحويل، ويمكنك أيضًا استدعاء الوظيفة المضمنة Swap عدة مرات، ولكن إذا فكرت في تعليمات BSWAP، يصبح كل شيء بسيطًا للغاية.
وظيفة SwapLong (القيمة: الكاردينال): الكاردينال؛
asm
بسواب إياكس
نهاية؛
ملاحظة: كما هو مذكور أعلاه، يتم تخزين قيمة القيمة في السجل EAX، ويتم أيضًا إرجاع القيمة المكونة من 32 رقمًا من خلال EAX، لذلك هناك حاجة إلى جملة واحدة فقط.
بالطبع، معظم تحسينات التجميع المضمنة ليست بهذه البساطة، ولكن من الصعب تحقيق المزيد من التحسين المتعمق باستخدام المعرفة القليلة بالتجميع التي تم تعلمها في الكلية، ولا يمكن اكتساب الخبرة إلا من خلال التراكم المستمر ومقارنة رموز التجميع المجمعة! ولحسن الحظ، في معظم الحالات، لا يكون التحسين التفصيلي هو الجزء الرئيسي من تصميم البرنامج.
ومع ذلك، إذا كان البرنامج الذي تم تطويره يتضمن رسومات وصور ووسائط متعددة وما إلى ذلك، فلا يزال من الضروري إجراء المزيد من التحسين المتعمق! لحسن الحظ، يمكن لـ Delphi6 تقديم دعم جيد سواء كان ذلك تحسين تعليمات الفاصلة العائمة أو تطبيق MMX، SSE، 3DNow، وما إلى ذلك. حتى إذا كنت تريد أن تدعم الإصدارات السابقة من دلفي مجموعات تعليمات وحدة المعالجة المركزية الموسعة هذه أو تريد دعم مجموعات تعليمات وحدة المعالجة المركزية الجديدة في المستقبل، فيمكنك استخدام تعليمات التجميع الأربعة لـ DB وDW وDD وDQ التي تدعمها دلفي في التجميع المضمن ( في دليل اللغة الرسمي لـ Borland's Delphi6 يقول دليل اللغة فقط أنه يدعم DB وDW وDD) ويمكن أيضًا تنفيذ التمثيل الرقمي للتعليمات ذات الصلة بمرونة.
يحب:
DW $A20F //CPUID
DW 770 دولارًا أمريكيًا //EMMS
DB $0F، $6F، $C1 //MOVQ MM0، MM1
إن فهم التعليمات هو الأساس فقط بعد تصميم الخوارزمية حول FPU وMMX وSSE، إذا كنت ترغب في تحسينها بشكل أكبر، فيجب عليك أيضًا فهم بعض الخصائص التقنية لوحدة المعالجة المركزية نفسها.
دعونا نلقي نظرة على القطعتين التاليتين من التعليمات البرمجية:
asm
إضافة [أ]، ECX
إضافة [ب]، إيدكس
نهاية
asm
موف إياكس، [أ]
موف إبكس، [ب]
إضافة EAX، ECX
إضافة إبكس، إدكس
موف [أ]، إياكس
موف [ب]، إبكس
نهاية
هل الثاني أكثر كفاءة؟ خطأ، كما ذكرنا سابقًا، عدد أقل من التعليمات لا يعني كفاءة تنفيذ عالية، وفقًا للمعلومات ذات الصلة، فإن دورة الساعة لتنفيذ التعليمتين في القسم الأول من الكود هي 3 (تحتاج كل تعليمات إلى إكمال ثلاث خطوات من القراءة، خطوة التعديل والكتابة)، دورات الساعة التي يتم تنفيذها بواسطة التعليمات الستة في القسم الثاني من التعليمات البرمجية كلها 1. إذن فإن قطعتي التعليمات البرمجية لهما نفس القدر من الكفاءة؟ وهذا خطأ مرة أخرى، فالجزء الثاني من التعليمات البرمجية يتم تنفيذه بكفاءة أكبر من الجزء الأول من التعليمات البرمجية! لماذا؟ نظرًا لأن وحدات المعالجة المركزية بعد فئة Pentium تحتوي على خطين لتنفيذ التعليمات، فعندما يمكن إقران تعليماتين متجاورتين، يمكن تنفيذهما في نفس الوقت! خاصة بالجزءين المذكورين أعلاه من التعليمات البرمجية، ما هي الأسباب المحددة؟
على الرغم من أنه يمكن إقران التعليمتين في الكود الأول، إلا أن إجمالي دورة ساعة التنفيذ المطلوبة هو 5 بدلاً من 3، بينما يمكن تنفيذ التعليمات الستة في الكود الثاني بالتوازي، مما يؤدي إلى هذه النتيجة.
بالحديث عن ذلك، هذه كلها أمثلة بسيطة جدًا، والتي في حد ذاتها لا يمكنها أن تقدم لك الكثير من المساعدة. إذا كنت تريد حقًا تحسين برنامج معين، فيجب عليك البحث عن بعض المقالات الخاصة حول تحسين FPU وMMX، أو العثور على أدلة تقنية لدراسة ودراسة التقنيات مثل "التنفيذ خارج الترتيب" و"التنبؤ بالفرع". أتمنى فقط ألا يركز جميع أصدقائي الموجودين في الكلية على أدوات التطوير "التي تدر المال" والتقنيات الجديدة العصرية فحسب، بل يمكنهم قضاء المزيد من الوقت في وضع الأساس، وباستخدام أساس متين، يمكنك إتقان المعرفة الجديدة بسرعة ، بهذه الطريقة فقط يمكننا إتقان أدوات ومهارات التطوير الجديدة في وقت أسرع... (احذف ألف كلمة).
ولكن مرة أخرى، لا يزال يتعين استخدام المعرفة لحل المشكلات العملية. إذا ركزت فقط على التفاصيل التقنية كل يوم، فقد تصبح متسللًا ممتازًا، لكنك لن تتمكن أبدًا من تطوير برامج من الدرجة الأولى. لذلك، يجب أن يظل الهدف الأساسي هو خلق القيمة. لذا... لن أتحدث عن ذلك بعد الآن، ولن يبدو حقًا كمقالة فنية إذا تحدثت عنه بعد الآن. ^_^
المرفقات: بالإضافة إلى مراعاة كفاءة التنفيذ، يجب أن يأخذ تحسين البرنامج أيضًا في الاعتبار مشكلات الحجم (يمكن للحجم الصغير تحميل الذاكرة بشكل أسرع وإكمال فك تشفير التعليمات والمهام الأخرى بشكل أسرع). على سبيل المثال، لمسح سجل EAX، استخدم SUB EAX أو EAX أو XOR EAX ، EAX بدلاً من MOV EAX، $0 على الرغم من أن دورات ساعة التنفيذ الخاصة بها تبلغ 1، فمن الواضح أن طول تعليمات الأولى (2 بايت) أقصر من طول الأخيرة (5 بايت). لكن لأن ما ذكر أعلاه كله تفاصيل، لم يتم ذكر مسألة الحجم. يجب ترك المزيد من مشكلات تقليل الحجم للمترجم لحلها. فقط انتبه قليلاً عند كتابة كود ASM المضمن.