تحسين ما بين الإجراءات

تحسين الأداء بين الإجراءات ( IPO ) هو مجموعة من تقنيات المُترجمات المستخدمة في برمجة الحاسوب لتحسين أداء البرامج التي تحتوي على العديد من الدوال قصيرة أو متوسطة الطول شائعة الاستخدام. ويختلف تحسين الأداء بين الإجراءات عن تحسينات المُترجمات الأخرى في تحليله للبرنامج بأكمله بدلاً من دالة واحدة أو جزء من التعليمات البرمجية.

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

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

بالنسبة للغات التي تُترجم على أساس ملف بملف، يتطلب تحسين أداء البرنامج (IPO) الفعال عبر وحدات الترجمة (ملفات الوحدات) معرفة "نقاط الدخول" للبرنامج حتى يتسنى تشغيل تحسين البرنامج الكامل ( WPO ). في كثير من الحالات، يُنفذ هذا كخطوة تحسين وقت الربط ( LTO )، لأن البرنامج بأكمله مرئي للرابط.

تحليل

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

لأسبابٍ عديدة، منها سهولة القراءة، تُقسّم البرامج عادةً إلى عددٍ من الإجراءات التي تعالج حالاتٍ عامة قليلة. مع ذلك، قد تؤدي عمومية كل إجراء إلى هدر الجهد في استخداماتٍ محددة. يُمثّل تحسين ما بين الإجراءات محاولةً للحدّ من هذا الهدر.

لنفترض وجود إجراء يُقيّم قيمةً ما f(x)، وأن هذه fالدالة نقية ، وأن الكود يطلب نتيجة التقييم الأول f(6)، ثم يطلبها مرة أخرى لاحقًا f(6). من شبه المؤكد أن هذا التقييم الثاني غير ضروري: إذ كان من الممكن حفظ النتيجة والرجوع إليها لاحقًا. يُفقد هذا التحسين البسيط جدواه بمجرد أن f(x)يصبح تنفيذ الدالة غير نقي؛ أي عندما يتضمن مراجع لمعاملات أخرى غير الوسيط المُحدد 6الذي تم تغييره بين الاستدعاءات، أو آثارًا جانبية مثل طباعة رسالة في سجل، أو حساب عدد التقييمات، أو تجميع وقت وحدة المعالجة المركزية المُستهلك، أو إعداد جداول داخلية لتسهيل الاستدعاءات اللاحقة للمعاملات ذات الصلة، وما إلى ذلك. قد يكون فقدان هذه الآثار الجانبية نتيجة عدم التقييم مرة ثانية مقبولًا، أو قد لا يكون كذلك.

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

WPO و LTO

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

يُعدّ تحسين وقت الربط ( LTO ) نوعًا من أنواع تحسين البرامج التي يُجريها المُصرّف على البرنامج أثناء عملية الربط . ويُعدّ تحسين وقت الربط ذا أهمية في لغات البرمجة التي تُصرّف البرامج على أساس كل ملف على حدة، ثم تربط تلك الملفات معًا (مثل لغتي C و Fortran )، بدلاً من ربطها جميعًا دفعة واحدة (مثل الترجمة الفورية في Java (JIT)).

بعد تجميع جميع الملفات بشكل منفصل إلى ملفات كائنية ، يقوم المترجم عادةً بربط (دمج) هذه الملفات في ملف واحد، وهو الملف التنفيذي . مع ذلك، في تقنية تحسين وقت الربط (LTO) كما هو مُطبق في مجموعة مترجمات جنو (GCC) و LLVM ، يستطيع المترجم استخراج تمثيله الوسيط (IR)، أي بايت كود GIMPLE أو بت كود LLVM، على التوالي، بحيث يمكن تحسين جميع وحدات التجميع المختلفة التي ستُشكل ملفًا تنفيذيًا واحدًا كوحدة واحدة عند اكتمال عملية الربط. يُوسع هذا نطاق التحسينات بين الإجراءات ليشمل البرنامج بأكمله (أو بالأحرى، كل ما هو مرئي أثناء الربط). بفضل تحسين وقت الربط، يستطيع المترجم تطبيق أشكال مختلفة من التحسينات بين الإجراءات على البرنامج بأكمله، مما يسمح بتحليل أعمق، وتحسينات أكثر، وبالتالي أداء أفضل للبرنامج.

عمليًا، لا يُحسّن LTO البرنامج بأكمله دائمًا، إذ تُستبعد وظائف المكتبة ، وخاصةً الكائنات المشتركة المرتبطة ديناميكيًا ، عمدًا لتجنب التكرار المفرط ولإتاحة التحديث. يُسهّل الربط الثابت مفهوم LTO، لكنه يعمل فقط مع أرشيفات المكتبات التي تحتوي على كائنات IR، وليس مع ملفات كائنات لغة الآلة فقط. [ 1 ] ونظرًا لاعتبارات الأداء، لا تُستخدم الوحدة بأكملها دائمًا بشكل مباشر، إذ يُمكن تقسيم البرنامج باستخدام LTO بأسلوب فرق تسد، مثل WHOPR في GCC. [ 2 ] وبالطبع، عندما يكون البرنامج المُنشأ مكتبةً بحد ذاته، يحتفظ التحسين بكل رمز مُتاح خارجيًا (مُصدّر)، دون بذل جهد كبير لإزالته كجزء من DCE. [ 1 ]

لا يزال من الممكن تطبيق شكل محدود للغاية من تحسين نقطة الدخول (WPO) دون استخدام تحسين وقت التشغيل (LTO)، كما يتضح من -fwhole-programمفتاح التبديل في GCC. في هذا الوضع، يفترض GCC أن الوحدة النمطية التي يتم تجميعها تحتوي على نقطة دخول البرنامج بأكمله، بحيث لا يتم استخدام أي دالة أخرى فيها خارجيًا، ويمكن تحسينها بأمان. ولأنه ينطبق على وحدة نمطية واحدة فقط، فإنه لا يشمل البرنامج بأكمله. يمكن دمجه مع تحسين وقت التشغيل (LTO) في سياق وحدة نمطية واحدة كبيرة، وهو أمر مفيد عندما لا يُبلغ الرابط GCC بنقاط الدخول أو الرموز المستخدمة خارجيًا. [ 1 ]

تاريخ

بالنسبة للغات الإجرائية مثل ALGOL ، يبدو أن التحليل والتحسين بين الإجراءات قد دخلا حيز الممارسة التجارية في أوائل سبعينيات القرن العشرين. أجرى مُجمِّع PL/I المُحسِّن من IBM تحليلًا بين الإجراءات لفهم الآثار الجانبية لكلٍّ من استدعاءات الإجراءات والاستثناءات (التي تُعرف في PL/I باسم "الشروط") [ 3 ] ، كما ورد في أوراق بحثية لفران ألين . [ 4 ] [ 5 ] وكان العمل على تجميع لغة برمجة APL بالضرورة تحليلًا بين الإجراءات. [ 6 ] [ 7 ]

كانت تقنيات التحليل والتحسين بين الإجراءات موضوعًا للبحث الأكاديمي في ثمانينيات وتسعينيات القرن الماضي. ثم عادت للظهور في عالم المترجمات التجارية في أوائل التسعينيات مع مترجمات من شركة كونفكس كمبيوتر (مترجم التطبيقات لجهاز كونفكس C4) ومن شركة أردنت (مترجم جهاز أردنت تايتان ). أثبتت هذه المترجمات إمكانية تطوير هذه التقنيات بسرعة كافية لتكون مقبولة في المترجمات التجارية؛ ومنذ ذلك الحين، ظهرت تقنيات التحليل والتحسين بين الإجراءات في عدد من الأنظمة التجارية وغير التجارية.

الأعلام والتنفيذ

شبيهة بنظام يونكس

تتيح مجموعة مُترجمات GNU تضمين الدوال في جميع مستويات التحسين. -O1ينطبق هذا فقط على الدوال التي تُستدعى مرة واحدة -finline-functions-once، بينما -O2يُخفف هذا القيد -finline-functions. افتراضيًا، يقتصر هذا السلوك على ملف واحد فقط، ولكن مع تحسين وقت الربط، -fltoيشمل البرنامج بأكمله. [ 1 ] واجهة سطر أوامر Clang مشابهة لواجهة GCC، باستثناء عدم وجود -fwhole-programخيار. [ 8 ]

تحتوي ملفات الكائنات الناتجة عن تقنية LTO على تمثيل وسيط خاص بالمترجم (IR) يُفسَّر أثناء عملية الربط. ولضمان توافقها مع المكتبات الثابتة ، توفر روابط GNU الأحدث واجهة "ملحق الرابط" التي تسمح للمترجم بتحويل ملفات الكائنات إلى صيغة لغة الآلة عند الحاجة. كما يُسهم هذا الملحق في تحسين عملية LTO بشكل عام. بدلاً من ذلك، يمكن إنشاء كائن "LTO ضخم" يحتوي على كلٍّ من لغة الآلة والتمثيل الوسيط، ولكن هذا يتطلب مساحة أكبر. [ 1 ]

بما أن كلاً من GCC وLLVM (clang) قادران على إنتاج تمثيل وسيط من لغات برمجة متنوعة، فإنّ عملية نقل البيانات في وقت الربط ممكنة حتى عبر حدود اللغات. ويتضح هذا جلياً مع لغتي C وC++، [ 9 ] ولكن LLVM يُتيح ذلك أيضاً للغة Rust وجميع المترجمات الأخرى القائمة على LLVM. [ 10 ]

خيارات غير محدودة المدة

يُجري كل من GCC وClang عملية تحسين الإدخال/الإخراج (IPO) افتراضيًا عند مستوى التحسين 2. مع ذلك، تكون درجة التحسين محدودة عند تعطيل LTO، إذ لا يمكن إجراء IPO إلا داخل ملف الكائن، ولا يمكن حذف الدوال غير الثابتة . يُمكن حل هذه المشكلة الأخيرة دون استخدام LTO: حيث -fwhole-programيُمكن استخدام الخيار `--` لافتراض أن `include` فقط main()هو غير ثابت، أي مرئي من الخارج. [ 11 ]

هناك تقنية أخرى غير تقنية LTO تُسمى "أقسام الدوال" ( -ffunction-sectionsفي GCC وClang). فبوضع كل دالة في قسم خاص بها في ملف الكائن، يستطيع الرابط إزالة الأجزاء غير المستخدمة من الكود دون الحاجة إلى تمثيل وسيط (IR) عن طريق حذف الأقسام غير المُشار إليها (باستخدام خيار الرابط --gc-sections). [ 12 ] يتوفر خيار مشابه للمتغيرات، ولكنه يُنتج كودًا أسوأ بكثير.

آخر

تسمح مُجمِّعات Intel C/C++ بتحسين الأداء بين الإجراءات على مستوى البرنامج بأكمله. يُستخدم الخيار `--` لتفعيل تحسين الأداء بين الإجراءات لملف واحد -ip، بينما يُستخدم الخيار `--` لتفعيل تحسين الأداء بين الإجراءات على مستوى جميع ملفات البرنامج -ipo. [ 13 ] [ 14 ]

يدعم مُصرّف MSVC ، المُدمج في Visual Studio، أيضًا تحسين الأداء بين الإجراءات على مستوى البرنامج بأكمله. [ 15 ]

يتم توفير واجهة مستقلة عن المترجم لتمكين التحسينات بين الإجراءات للبرنامج بأكمله من خلال INTERPROCEDURAL_OPTIMIZATIONالخاصية الموجودة في CMake . [ 16 ]

انظر أيضاً

مراجع

  1. ١ ٢ ٣ ٤ ٥ "خيارات التحسين" . باستخدام مجموعة مترجمات جنو (GCC) . لا تتطلب تحسينات وقت الربط وجود البرنامج بأكمله للعمل. إذا كان البرنامج لا يتطلب تصدير أي رموز، فمن الممكن الجمع بين الخيارين -flto و-fwhole-program للسماح لمُحسِّنات ما بين الإجراءات باستخدام افتراضات أكثر صرامة، مما قد يؤدي إلى تحسين فرص التحسين. لا يلزم استخدام الخيار -fwhole-program عند تفعيل مُلحق الرابط (انظر -fuse-linker-plugin).
  2. "نظرة عامة على LTO" . المكونات الداخلية لمجموعة مترجمات GNU (GCC) .
  3. توماس سي. سبلمان، "الكشف عن الآثار الجانبية في مترجم PL/I الأمثل"، في وقائع IFIPS 1971 ، شركة نورث هولاند للنشر، الصفحات 376-381.
  4. فرانسيس إي. ألين، "تحليل تدفق البيانات بين الإجراءات"، وقائع IFIPS، 1974.
  5. فرانسيس إي. ألين، وجاك شوارتز، "تحديد علاقات تدفق البيانات في مجموعة من الإجراءات"، تقرير بحثي لشركة IBM رقم RC 4989، أغسطس 1974.
  6. فيليب أبرامز ، "آلة APL"، قسم علوم الحاسوب بجامعة ستانفورد، التقرير STAN-CS-70-158، فبراير 1970.
  7. تيرينس سي. ميلر، "التجميع المؤقت: تصميم لمترجم لغة APL"، أطروحة دكتوراه، جامعة ييل، 1978.
  8. "مرجع وسيطات سطر أوامر Clang" . وثائق Clang 11 .
  9. راينهارت، جوناثان. "هل يمكن لتقنية LTO في gcc أو clang تحسين الأداء عبر طرق C و C++؟" . ستاك أوفرفلو .
  10. ووريستر، مايكل (19 سبتمبر 2019). "سد الفجوة: تحسين حجم البيانات بين لغات Rust و C/C++" . مدونة مطوري LLVM .
  11. "خيارات التحسين" . استخدام مجموعة مترجمات جنو (GCC) .
  12. "أقسام الوظائف" . elinux.org .
  13. "وثائق مُترجم إنتل 8" . مؤرشف من الأصل بتاريخ 21-09-2006 . تم الاطلاع عليه بتاريخ 13-02-2007 .
  14. مُجمِّع إنتل فيجوال فورتران 9.1، الإصداران القياسي والاحترافي، لنظام التشغيل ويندوز* - شبكة برامج إنتل
  15. "/GL (تحسين البرنامج بالكامل)" . مستندات مايكروسوفت . 12-03-2019 . تم الاطلاع عليه بتاريخ 26-01-2020 .
  16. "INTERPROCEDURAL_OPTIMIZATION" . CMake 3.17.2 Documentation .
  • كيف يمكن خداع مترجمات لغة C/C++ لإنتاج كود رديء؟