تنبؤ (حوسبة)
قبل الخوض في التفاصيل، التنبؤ في هندسة الحاسوب هو ميزةً تُوفّر بديلاً عن نقل التحكم المشروط، كما هو مُطبّق في تعليمات التفرع المشروط. يعمل التنبؤ من خلال ربط تعليمات غير متفرعة (مُنْبَذَلة) بمُنْبَذَل، وهو قيمة منطقية تستعملها التعليمات للتحكم فيما إذا كان مسموحًا لها بتعديل حالة المعمارية أم لا. إذا كان المُنْبَذَل المُحدّد في التعليمات صحيحًا، فإنّ التعليمات تُعدّل حالة المعمارية؛ وإلا، تبقى حالة المعمارية دون تغيير. مثلًا، لن تُعدّل تعليمات النقل المُنْبَذَلة (نقل مشروط) الوجهة إلا إذا كان المُنْبَذَل صحيحًا. وبالتالي، بدلاً من استخدام التفرع المشروط لاختيار تعليمات أو سلسلة من التعليمات للتنفيذ بناءً على المُنْبَذَل الذي يتحكّم في حدوث التفرع، فإنّ التعليمات المراد تنفيذها مرتبطة بهذا المُنْبَذَل، بحيث يتم تنفيذها، أو عدم تنفيذها، بناءً على ما إذا كان هذا المُنْبَذَل صحيحًا أم خاطئًا. وفيما يلي تفاصيل أوسع عن ذلك.
من جانب آخر، تعتمد المعالجات المتجهية، وبعض مجموعات التعليمات متعددة البيانات (مثل الامتدادات المتجهية المتقدمة 2 والامتداداتٍ المتجهية المتقدمة ذات 512 بت)، ووحدات معالجة الرسومات عمومًا، إلى حدّ كبير على التنبؤ، حيث يتم تطبيق بت واحدة من متجه قناع شرطي على العناصر المقابلة في سجلات المتجهات التي تكون قيد المعالجة، بينما لا يحتاج التنبؤ العددي في مجموعات التعليمات العددية إلا إلى بت واحدة للتنبؤ. وتبرز قوة أقنعة التنبؤ بشكل خاص في معالجة المتجهات عندما يمكن لمصفوفة من رموز الحالة، رمز واحد لكل عنصر من عناصر المتجه، أن تُغذي أقنعة التنبؤ التي تُطبق بدورها على تعليمات المتجهات اللاحقة.
نظرة عامة
وعلى صعيد آخر، تحتوي أغلب برامج الحاسوب على تعليمات برمجية مشروطة تُنفَّذ فقط في ظروف محددة بناءً على عوامل لا يمكن تحديدها مسبقًا، مثل مدخلات المستعمل. ولأن أغلب المعالجات تُنفِّذ ببساطة التعليمات التالية في التسلسل، فإن الحل التقليدي لذلك هو إدراج تعليمات التفرع التي تسمح للبرنامج بالانتقال بشكل مشروط إلى قسم مختلف من التعليمات البرمجية، وبالتالي تغيير الخطوة التالية في التسلسل. كان ذلك كافيًا إلى أن بدأ المصممون في تحسين الأداء من خلال تطبيق تقنية خطوط أنابيب التعليمات، وهي طريقة تُبطئها التفرعات. هُناك لحسن الحظ، حلولًا أكثر ذكاءًا لأحد أنماط التعليمات البرمجية الأكثر شيوعًا، والتي تعتمد عادةً على التفرعات، كما يتضح من النص البرمجي المفترض التالي:if condition
{do_something}
else
إضافةً إلى ذلك، {do_something_else}قد يُترجم هذا النص البرمجي المفترض في نظام يستعمل التفرع الشرطي إلى تعليمات لغة آلة مشابهة لما يلي: branch_if_condition_to label1
do_something_else
do_something
وفي هذا الصدد، يُعدّ التنبؤ الجزئي هو أبسط أشكال التنبؤ، حيث تحتوي معمارية النظام على تعليمات نقل مشروطة أو تعليمات اختيار مشروطة. تكتب تعليمات النقل المشروطة محتويات سجل فوق سجل آخر فقط إذا كانت قيمة الشرط صحيحة، بينما تختار تعليمات الاختيار المشروطة أي سجلين سيتم كتابة محتوياته في سجل ثالث بناءً على قيمة الشرط. أما التنبؤ الكامل فهو الشكل الأكثر عمومية وكفاءة من أشكال التنبؤات، حيث تتضمن عملية التنبؤ الكامل مجموعة من سجلات التنبؤ لتخزين التنبؤات (مما يسمح بحذف عدة فروع متداخلة أو متسلسلة في آن واحد)، وتحتوي أغلب التعليمات في هذه المعمارية على حقل مُحدد سجل (اختياري) لتحديد سجل التنبؤ الذي يُوفر التنبؤ.
ومن جهة أخرى، ...في حالة التنبؤ، تُكتب جميع مسارات التفرع الممكنة مباشرةً في النص البرمجي، وتُنفذ بعض التعليمات على حين لا تُنفّذ تعليمات أخرى. تكمن الفكرة الأساسية في أن كل تعليمة مرتبطة بمسند (يُستعمل المصطلح هنا بشكل مشابه لاستخدامه في منطق المسندات)، وأن التعليمة لن تُنفّذ إلا إذا كان المسند صحيحًا. وفي هذه الحالة قد يبدو النص البرمجي للآلة في المثال السابق باستخدام التنبؤ على النحو التالي:(condition) do_something
إضافةً إلى ذلك، (not condition) do_something_elseبالإضافة إلى إلغاء التفرعات، يؤدي التنبؤ إلى تقليل الحجم الإجمالي للنص البرمجي المطلوب شريطة أن تدعم معمارية النظام تعليمات التنبؤ. وعلى الرغم من أن هذا لا يضمن سرعة تنفيذ أعلى عمومًا، إلا أنه سيضمنها إذا كانت كتلتا التعليمات البرمجية do_something و do_something_else قصيرتين بما يكفي.
label2:
المميزات
من جهة ثانية، يساهم التنبؤ في التخلص من تكلفة التنبؤ الخاطئ بالتفرع، والتي قد تكون مرتفعة في المعماريات ذات التسلسل العميق.
من جانب آخر، يمكن دمج التعليمات المتنبأ بها ذات الشروط المختلفة مع بعضها البعض ومع التعليمات غير المشروطة، مما يسمح بجدولة أفضل للتعليمات وبالتالي أداء أفضل.
من جانب آخر، يمكن لمجموعات التعليمات التي تحتوي على رموز شرطية شاملة مُولّدة بواسطة التعليمات أن تُقلل حجم الكود بشكل أكبر من خلال استخدام سجلات الحالة مباشرةً في التنبؤ أو كبديل عنه.
ومن ناحية أخرى، يتمثل الهدف الرئيسي من التنبؤ في تجنب التفرعات التي تتسبب في القفز عبر أجزاء صغيرة جدًا من رماز البرنامج، مما يزيد من فعالية التنفيذ المتسلسل ويتجنب مشكلات الذاكرة المؤقتة. يمتلك التنبؤ عددًا من المزايا الأخرى، حيث:
وفي هذا السياق، يُمكن تنفيذ الدوال التي تُحسب عادةً باستخدام العمليات الحسابية البسيطة والعمليات على مستوى البتات بشكل أسرع باستخدام التعليمات المتنبأ بها.
إضافةً إلى ذلك، يمكن أن يؤدي حذف تعليمات التفرع غير الضرورية إلى تسريع تنفيذ التفرعات الضرورية، مثل تلك التي تُشكل الحلقات، عن طريق تقليل الحمل على آليات التنبؤ بالتفرعات.
branch_always_to label2
label1:
العيوب
كذلك، يتمثل العيب الرئيسي للتنبؤ في زيادة مساحة التشفير. في التطبيقات النموذجية، تحجز كل تعليمة حقل بتات للشرط الذي يحدد الشروط التي يجب أن تُنفذ بموجبها. عندما تكون الذاكرة المتاحة محدودة، كما هو الحال في الأجهزة المدمجة، قد تكون تكلفة هذه المساحة باهظة. مع ذلك، تستطيع بعض المعماريات، مثل معمارية ثامب-2، تجنب هذه المشكلة. ومن العيوب الأخرى للتنبؤ ما يلي:
من جهة ثانية، تتضمن الكتلة المُتنبّأة دورات لجميع العمليات، لذا قد تستغرق المسارات الأقصر وقتًا أطول وتُعاقب.
كذلك، يُعقّد التنبؤ تصميم الجهاز بإضافة مستويات منطقية إلى المسارات الحرجة، وقد يُؤدي إلى انخفاض تردد الساعة.
وفي هذا الصدد، يتطلب الأمر قراءة سجل إضافي. تقرأ عملية الجمع غير المُتنبّأة سجلين من ملف السجلات، بينما تحتاج عملية الجمع المُتنبّأة إلى قراءة ملف سجل الحالة كذلك. ويزيد هذا من مخاطر التنفيذ الديناميكي.
من جانب آخر، لا يُمكن التوقع بالتنبؤ عادةً، مما يُؤدي إلى سلسلة تبعية أطول. يُترجم هذا بالنسبة للبيانات المُرتبة إلى انخفاض في الأداء مقارنةً بالتفرع المُتوقع.
علاوةً على ذلك، يكون التنبؤ أكثر فعالية عندما تكون المسارات متوازنة أو عندما يكون أطول مسار هو الأكثر تنفيذًا بشكل متكرر، غير أن تحديد مثل هذا المسار يُعتبر أمر صعب للغاية في وقت الترجمة، حتى في ظل وجود معلومات تحليل الأداء.
📝 هل في هذه المقالة خطأ؟
إذا وجدت معلومة تحتاج تصحيحاً أو إضافة، أو أردت حذف المقالة، أرسل لنا طلباً وسنراجعه.
ما رأيك في هذه المقالة؟