سنبدأ بشرح الدور المهم، الذي يلعبه طاقم التعليمات (instruction set)، ثم ننتقل إلى إلقاء نظرة فاحصة على تطور عائلة معالجات إنتل. ونشرح أيضاً، بعض المصطلحات الأخرى، التي قد تجد الإلمام بها مفيداً.
التعليمات
تعمل الكمبيوترات بناءً على أوامر متدنية المستوى (low-level commands)، تُدعى التعليمات (instructions). ونقصد بعبارة "متدنية المستوى"، أن هذه الأوامر تعمل بشكل مباشر مع المعالج، وتتصل مع أجزائه الأساسية. ويحتوي كل نوع من أنواع المعالجات، على مجموعة محددة من هذه التعليمات، التي يعمل بموجبها. وتسمّى هذه المجموعة طاقم التعليمات (instruction set).
يمكن للمبرمجين الوصول إلى تعليمات المعالج من خلال لغات البرمجة المختلفة. وتكتب زمرة التعليمات بلغة الآلة (machine language)، التي تحتل أدنى مستوى من بين جميع اللغات، وتتألف من أرقام فقط (الصفر والواحد)، ولذلك يندر استخدامها من قبل المبرمجين. وللتغلب على هذه المشكلة، يلجأ المبرمجون عادة، إما إلى اللغة التجميعية (assembly language)، التي تستخدم التعليمات ذاتها، لكنها تعطي تسميات محددة لتسهيل التعامل معها (مثل add و inc)، وإما إلى لغة عالية المستوى (high-level language , HLL)، تندرج فيها تعليمات الآلة ضمن أوامر على نطاق أوسع. ويبيّن الشكل المستويات المختلفة للغات البرمجة.
لا تستغني اللغات عالية المستوى (HLL) عن تعليمات الآلة بأي شكل، لكنها تجعل التعامل معها أسهل، نسبياً. يجب تحويل البرنامج المكتوب بلغة عالية المستوى، إلى لغة الآلة، ويتم ذلك عن طريق البرنامج المترجم (compiler) الخاص بهذه اللغة، ويقوم برنامج المترجم عادة بتحويل تعليمات البرنامج إلى لغة داخلية وسيطة أولاً، ثم إلى لغة الآلة. وتسمّى هاتان المرحلتان: الواجهة الأمامية (front end)، والواجهة الخلفية (back end) للمترجم. ويمكن لمصممي البرنامج المترجم (compiler) أن يفصلوا الأجزاء التي لا تتعلق بمعمارية منصة العمل، عن الأجزاء المتعلقة بها. ويجب في نهاية المطاف، أن تصل التعليمات إلى المعالج على هيئة أرقام، لكي يتمكّن من القيام بعمله.
تتضمن التعليمات النموذجية في طاقم تعليمات x86، التي شكّلت حجر الأساس لبيئة الكمبيوترات الشخصية لسنين طويلة، أوامر لفعاليات مختلفة، مثل التوابع الحسابية، ونقل البيانات، والتعليمات المنطقية، وتعليمات الدخل والخرج. وتتضمن التعليمات الحسابية أمر add، الذي يضيف محتويات المسجّلات (registers) المختلفة إلى بعضها البعض، وأمر inc (increment) الذي يضيف واحداً إلى القيمة الموجودة في المسجّل. وتتضمّن تعليمات نقل البيانات أمر mov الذي ينقل البيانات من مسجّل إلى مسجّل آخر، أو إلى عنوان ذاكرة، وأمر xchng (exchange) الذي يقوم بتبديل محتويات مسجّلين مختلفين بين بعضهما البعض، أو محتويات عنواني ذاكرة. وتتألف كافة البرامج من مزيج متنوع من هذه التعليمات التي "يفهمها" المعالج وينفذها.
التصاميم فائقة التدرج
تحدثنا في الجزء السابق عن خطوط المعالجة (pipelines)، وهي التقنية التي تمكّن المعالج من البدء في تنفيذ تعليمة جديدة، قبل أن ينتهي من تنفيذ التعليمة الحالية. وتمكّننا هذه التقنية من توفير الوقت، عن طريق التأكّد من أن المعالج لن يتوقف في انتظار التعليمات. ولا يستطيع المعالج في جميع الأحوال، إنهاء سوى تعليمة واحدة خلال دورة الساعة الواحدة. ولزيادة المردود، وتسريع المعالجة، تمتاز معالجات اليوم (مثل معالج Alpha، من شركة كومباك -بعد أن اشترت ديجيتال- ومعالج Power PC من شركتي IBM وموتورولا، ومعالجات بينتيوم من إنتل، ومعالج SPARC من صن) باحتوائها على معمارية التدرج الفائق (superscalar). وتكمن الفائدة الرئيسية لمعمارية التدرج الفائق في أنها تسمح للمعالج بتنفيذ أكثر من تعليمة في دورة الساعة الواحدة، باستخدام عدة خطوط معالجة.
يبحث المعالج ذو التصميم فائق التدرج، عن التعليمات التي يمكن معالجتها خلال دورة الساعة ذاتها، ويعالجها مع بعضها البعض. فيمكن، مثلاً، لمعالج بينتيوم، العمل على تعليمات بسيطة، مثل mov و or و add، بهذه الطريقة، تحت ظروف خاصة فقط (يجب أن لا تكون إحدى التعليمات بحاجة إلى نتيجة التعليمات الأخرى). لكن التعليمات الأكثر تعقيداً، كالتي تتضمّن عمليات الفاصلة العائمة، لا يمكن معالجتها معاً.
تقدّم المعالجة المتوازية (parallel processing) فوائد واضحة في مجال السرعة، لكن تقنية التدرج الفائق (superscalar) لها نقادها. ويعتقد البعض أنها تضيّع العديد من الفرص على التنفيذ المتوازي، لأن دمج التعليمات المنفصلة يأخذ وقتاً كبيراً نسبياً، ولأن التعليمات المنفصلة غالباً ما تتأخر أثناء إنتظارها للموارد. لنفرض، مثلاً، أن التعليمة A تنفذ في أحد خطوط المعالجة، فيما تنفذ التعليمة B في خط آخر، وتنتظر التعليمة C أن ينتهي خط التنفيذ الأول من تنفيذ التعليمة A. وعند الإنتهاء من تنفيذ التعليمة A، فإن الشيء الواضح هو استبدالها بالتعليمة C، وهي التعليمة التالية على خط التنفيذ. لكن، إذا كانت التعليمة C تحتاج إلى نتائج التعليمة B، التي يتم تنفيذها في خط التنفيذ المتتابع الآخر، فعليها أن تنتظر. وهذا ما يقضي على فكرة التنفيذ المتوازي، ويقضي على أية فرصة لزيادة السرعة. ويصبح، بذلك، لمعالجك الجديد المكلف دور محدود نسبياً، في زيادة الأداء.
وحتى في البرنامج المصمم بشكل جيد -الذي يحاول أن يحصل على الفائدة القصوى من خطوط المعالجة والتنفيذ المتوازي- يمكن أن تعاني خطوط المعالجة من تأخيرات زمنية. وللتغلب على هذه المشكلة، صمم المهندسون معالجات التدرج الفائق، لتقوم بأداء التنفيذ غير المرتّب (out-of-order execution). فإذا كان أحد خطوط المعالجة حراً، نظراً لأن التعليمة C تحتاج لنتائج التعليمة B، فإن المعالج يمكنه أن يبحث عن أول تعليمة في البرنامج لا تعتمد على التعليمة B (ولتكن التعليمة H). ويبدأ المعالج بالعمل على التعليمة H والتعليمات المرتبطة بها، إلى أن تنتهي التعليمة B، حيث يعود بعدها إلى التعليمة C. وبدلاً من إرسال نتائج التعليمة غير المرتّبة إلى المسجّلات (حيث يتعامل المعالج بشكل مباشر مع البيانات)، فإن المعالج يرسلها إلى ذاكرة وسيطة لتخزينها، ثم يقوم بترتيب كل شيء بانتظام، قبل تحريره.
تظهر إحدى مشاكل التنفيذ غير المرتّب إذا احتاجت تعليمتان إلى المسجّل ذاته. وللتغلب على هذه المشكلة، فإن معالجات اليوم يمكنها أن تغيّر أسماء المسجّلات بشكل فوري، ضمن عملية "إعادة تسمية المسجّلات" (register renaming). ومن الواضح أن التنفيذ غير المرتّب يتطلب تصميماً دقيقاً جداً للمعالج، لأن البرامج قد تفشل في عملها، إذا لم يتم تنفيذ التعليمات بالترتيب الصحيح