التحويل التلقائي إلى متجه
في الحوسبة المتوازية ، تُعدّ المعالجة المتجهة التلقائية حالة خاصة من المعالجة المتوازية التلقائية ، حيث يُحوّل برنامج الحاسوب من تنفيذ قياسي ، يُعالج زوجًا واحدًا من المعاملات في كل مرة، إلى تنفيذ متجهي ، يُعالج عملية واحدة على عدة أزواج من المعاملات في آنٍ واحد. على سبيل المثال، تحتوي الحواسيب التقليدية الحديثة، بما في ذلك الحواسيب العملاقة المتخصصة ، عادةً على عمليات متجهة تُنفّذ عمليات متزامنة مثل عمليات الجمع الأربع التالية (عبر أجهزة SIMD أو SPMD ):
مع ذلك، في معظم لغات البرمجة، عادةً ما تُكتب حلقات تكرارية تُجري عمليات جمع متسلسلة للعديد من الأرقام. إليك مثال على حلقة تكرارية كهذه، مكتوبة بلغة C :
for ( i = 0 ; i < n ; i ++ ) c [ i ] = a [ i ] + b [ i ];يقوم مُترجم المتجهات بتحويل هذه الحلقات إلى سلاسل من عمليات المتجهات. تُجري عمليات المتجهات هذه عمليات جمع على كتل من العناصر من المصفوفات aو b. cيُعدّ التحويل التلقائي للمتجهات موضوعًا بحثيًا رئيسيًا في علوم الحاسوب.
خلفية
كانت الحواسيب القديمة تحتوي عادةً على وحدة منطقية واحدة، تُنفذ تعليمة واحدة على زوج واحد من المعاملات في كل مرة. ولذلك، صُممت لغات البرمجة وبرامجها للتنفيذ بالتسلسل. أما الحواسيب الحديثة، فتستطيع القيام بمهام متعددة في آن واحد. لذا، تقوم العديد من مُجمّعات البرامج المُحسّنة بعملية التوجيه التلقائي، حيث تُحوّل أجزاء من البرامج التسلسلية إلى عمليات متوازية.
تُحوّل تقنية معالجة الحلقات المتجهة الحلقات الإجرائية بتخصيص وحدة معالجة لكل زوج من المعاملات. تقضي البرامج معظم وقتها داخل هذه الحلقات، لذا يُمكن لهذه التقنية تسريعها بشكل ملحوظ، خاصةً عند التعامل مع مجموعات بيانات كبيرة. تُطبّق هذه التقنية في معالجات Intel MMX و SSE و AVX ، وفي معالجات Power ISA AltiVec ، وفي معالجات ARM NEON و SVE و SVE2، وفي معالجات RISC-V Vector Extension .
تُعيق العديد من القيود عملية التحويل إلى تعليمات متجهة. في بعض الأحيان، قد يُبطئ التحويل إلى تعليمات متجهة التنفيذ، على سبيل المثال بسبب تزامن خط الأنابيب أو توقيت نقل البيانات. يُحدد تحليل تبعية الحلقات الحلقات التي يُمكن تحويلها إلى تعليمات متجهة، بالاعتماد على تبعية البيانات للتعليمات داخل الحلقات.
الضمانات
يجب أن تحافظ عملية التحويل التلقائي إلى متجهات، مثل أي تحسين للحلقات أو أي تحسين آخر في وقت الترجمة، على سلوك البرنامج بدقة.
تبعيات البيانات
يجب مراعاة جميع التبعيات أثناء التنفيذ لمنع النتائج غير الصحيحة.
بشكل عام، يمكن بسهولة تحويل التبعيات الثابتة في الحلقات والتبعيات المعجمية الأمامية إلى متجهات، كما يمكن تحويل التبعيات المعجمية الخلفية إلى تبعيات معجمية أمامية. مع ذلك، يجب إجراء هذه التحويلات بأمان لضمان بقاء التبعية بين جميع العبارات كما هي في الأصل.
يجب معالجة التبعيات الدورية بشكل مستقل عن التعليمات المتجهة.
قد يفترض المترجم أحيانًا وجود تبعية بشكل مفرط. توفر بعض المترجمات توجيهًا يُسمى ivdep لإرشاد المترجم إلى تجاهل التبعيات. سيؤدي تطبيق هذا التوجيه بشكل خاطئ إلى نتائج غير صحيحة. [ 1 ]
دقة البيانات
يجب الحفاظ على دقة الأعداد الصحيحة (حجم البت) أثناء تنفيذ تعليمات المتجهات. ويجب اختيار تعليمة المتجه الصحيحة بناءً على حجم وسلوك الأعداد الصحيحة الداخلية. كذلك، عند التعامل مع أنواع الأعداد الصحيحة المختلطة، يجب توخي الحذر الشديد لترقيتها/خفضها بشكل صحيح دون فقدان الدقة. كما يجب توخي الحذر الشديد عند تمديد الإشارة (لأن عدة أعداد صحيحة تُخزّن داخل نفس السجل) وأثناء عمليات الإزاحة، أو العمليات التي تتضمن بتات الحمل التي كان من المفترض أخذها في الاعتبار لولا ذلك.
الفاصلة العائمة
يتم الاحتفاظ افتراضيًا بدلالات الفاصلة العائمة من معيار IEEE-754 ، مما يمنع في كثير من الأحيان استخدام المتجهات بشكل كامل. لنأخذ على سبيل المثال الحلقة البسيطة التالية التي تحسب مجموع عناصر مصفوفة:
دالة ` sum` تأخذ مصفوفة ` A` من نوع ` float` وقيمة ` n` من نوع ` int` . تقوم الدالة بحساب مجموع عناصر المصفوفة ` A` باستخدام الدالة ` sum` ، ثم تُعيد ` sum` .لأن عمليات الفاصلة العائمة ليست تجميعية (تغيير ترتيب الجمع يغير النتيجة)، لا يُسمح للمترجم بتحويل الحلقة إلى متجه. فقط عندما يُسمح للمترجم صراحةً بإعادة التجميع (إعادة ترتيب العمليات كما لو كانت تجميعية)، يمكنه الترجمة إلى شيء مشابه لما يلي: [ 2 ] : § الاختزالات
دالة جمع الأعداد العشرية ( أ ، ن ) { ...float sum = sum4 [ 0 ] + sum4 [ 1 ] + sum4 [ 2 ] + sum4 [ 3 ]; for ( int i = n / 4 ; i < n ; ++ i ) { sum += A [ i ]; }أعد المجموع ؛ }في هذه الحالة، ستختلف النتائج قليلاً عن الأصل، لكن خطأ التقريب التقاربي سيكون متشابهاً. هذا مثال على الاختزال .
تشير الاختلافات الكبيرة، حتى مع تجاهل معيار IEEE-754، عادةً إلى خطأ برمجي. ومن الأسباب الشائعة أن إعادة التجميع الكاملة قد تُفشل خوارزميات الجمع المُعَوَّض . ويمكن لأوامر أكثر تقييدًا، مثل عبارة الاختزال من OpenMP، أن توفر إعدادات أكثر دقة.
نظرية
لتحويل البرنامج إلى تعليمات متجهة، يجب على مُحسِّن المُصرِّف أولاً فهم التبعيات بين التعليمات وإعادة ترتيبها، إذا لزم الأمر. بمجرد تحديد هذه التبعيات، يجب على المُحسِّن ترتيب تعليمات التنفيذ بشكل صحيح، وتحويل التعليمات المناسبة إلى تعليمات متجهة، والتي تعمل على عناصر بيانات متعددة.
بناء مخطط التبعية
تتمثل الخطوة الأولى في بناء مخطط التبعية ، وتحديد العبارات التي تعتمد على بعضها البعض. يتضمن ذلك فحص كل عبارة وتحديد كل عنصر بيانات تصل إليه، وربط مُعدِّلات الوصول إلى المصفوفات بالدوال، والتحقق من تبعية كل وصول لجميع الوصولات الأخرى في جميع العبارات. يمكن استخدام تحليل الأسماء المستعارة للتأكد من أن المتغيرات المختلفة تصل إلى نفس المنطقة في الذاكرة (أو تتقاطع معها).
يحتوي مخطط التبعية على جميع التبعيات المحلية التي لا تتجاوز المسافة بينها حجم المتجه. لذا، إذا كان سجل المتجه 128 بتًا، ونوع المصفوفة 32 بتًا، فإن حجم المتجه هو 128/32 = 4. ولا ينبغي أن تؤدي أي تبعيات أخرى غير دورية إلى إبطال عملية التوجيه، نظرًا لعدم وجود أي وصول متزامن في نفس تعليمة المتجه.
لنفترض أن حجم المتجه يساوي 4 أعداد صحيحة:
for ( i = 0 ; i < 128 ; i ++ ) { a [ i ] = a [ i -16 ]; // 16 > 4، من الآمن تجاهل a [ i ] = a [ i -1 ]; // 1 < 4، يبقى على مخطط التبعية }التجميع
باستخدام الرسم البياني، يمكن للمُحسِّن بعد ذلك تجميع المكونات المتصلة بقوة (SCC) وفصل العبارات القابلة للتحويل إلى متجهات عن البقية.
على سبيل المثال، لنفترض جزءًا من برنامج يحتوي على ثلاث مجموعات من التعليمات داخل حلقة تكرارية: (SCC1+SCC2)، وSCC3، وSCC4، بهذا الترتيب، حيث يمكن تحويل المجموعة الثانية فقط (SCC3) إلى تعليمات متجهة. سيحتوي البرنامج النهائي حينها على ثلاث حلقات تكرارية، واحدة لكل مجموعة، مع تحويل الحلقة الوسطى فقط إلى تعليمات متجهة. لا يستطيع مُحسِّن البرنامج دمج الحلقة الأولى مع الأخيرة دون الإخلال بترتيب تنفيذ التعليمات، مما يُبطل الضمانات اللازمة.
اكتشاف المصطلحات
يمكن تحسين بعض التبعيات غير الواضحة بشكل أكبر بناءً على مصطلحات محددة.
على سبيل المثال، يمكن تحويل تبعيات البيانات الذاتية التالية إلى متجهات لأن قيمة القيم الموجودة على اليمين ( RHS ) يتم جلبها ثم تخزينها في القيمة الموجودة على اليسار، لذلك لا توجد طريقة لتغيير البيانات داخل عملية التعيين.
a [ i ] = a [ i ] + a [ i + 1 ];يمكن تحويل الاعتماد على الذات بواسطة الكميات القياسية إلى متجهات عن طريق حذف المتغيرات .
الإطار العام
ينقسم الإطار العام لتحويل الحلقات إلى متجهات إلى أربع مراحل:
- مقدمة : حيث يتم تجهيز المتغيرات المستقلة عن الحلقة لاستخدامها داخلها. يتضمن ذلك عادةً نقلها إلى سجلات متجهة بأنماط محددة تُستخدم في تعليمات المتجهات. هذا هو المكان المناسب أيضًا لإدراج فحص التبعية أثناء التشغيل. إذا قرر الفحص أن استخدام المتجهات غير ممكن، فانتقل إلى مرحلة التنظيف .
- الحلقة(ات) : جميع الحلقات المتجهة (أو غير المتجهة)، مفصولة بمجموعات SCCs حسب ترتيب ظهورها في الكود الأصلي.
- الخاتمة : إرجاع جميع المتغيرات المستقلة عن الحلقة، والاستقراءات، والاختزالات.
- التنظيف : قم بتنفيذ حلقات عادية (غير متجهة) للتكرارات في نهاية الحلقة التي لا تكون من مضاعفات حجم المتجه أو عندما تمنع عمليات التحقق في وقت التشغيل معالجة المتجه.
وقت التشغيل مقابل وقت الترجمة
لا يمكن التحقق من بعض عمليات التحويل إلى متجهات بشكل كامل أثناء الترجمة. على سبيل المثال، قد تُفشل دوال المكتبة عملية التحسين إذا كانت البيانات التي تعالجها مُقدمة من المُستدعي. حتى في هذه الحالات، يُمكن لعملية التحسين أثناء التشغيل تحويل الحلقات إلى متجهات أثناء التنفيذ.
يتم إجراء هذا الفحص في وقت التشغيل في مرحلة التمهيد ويوجه التدفق إلى التعليمات المتجهة إن أمكن، وإلا فإنه يعود إلى المعالجة القياسية، اعتمادًا على المتغيرات التي يتم تمريرها على السجلات أو المتغيرات العددية.
يمكن بسهولة تحويل الكود التالي إلى صيغة متجهة أثناء الترجمة، لأنه لا يعتمد على أي معلمات خارجية. كما تضمن اللغة أن أياً من المتغيرين لن يشغل نفس مساحة الذاكرة التي تشغلها أي متغيرات أخرى، لأنهما متغيرات محلية وتوجد فقط في مكدس التنفيذ .
int a [ 128 ]; int b [ 128 ]; // تهيئة bfor ( i = 0 ; i < 128 ; i ++ ) a [ i ] = b [ i ] + 5 ;من ناحية أخرى، لا يحتوي الكود أدناه على أي معلومات حول مواقع الذاكرة، لأن المراجع عبارة عن مؤشرات وقد تتداخل الذاكرة التي تشير إليها.
دالة حسابية ( int * a , int * b ) { int i ; for ( i = 0 ; i < 128 ; i ++ , a ++ , b ++ ) * a = * b + 5 ; }يكفي إجراء فحص سريع أثناء التشغيل على عنوان كل من a و b ، بالإضافة إلى مساحة تكرار الحلقة (128)، لتحديد ما إذا كانت المصفوفات متداخلة أم لا، وبالتالي الكشف عن أي تبعيات. (لاحظ أنه بدءًا من معيار C99، فإن تحديد المعاملات باستخدام الكلمة المفتاحية restrict - هنا: int *restrict a, int *restrict b) - يُخبر المُصرّف بأن نطاقات الذاكرة التي يُشير إليها a و b لا تتداخل، مما يؤدي إلى نفس نتيجة المثال أعلاه).
توجد بعض الأدوات لتحليل التطبيقات الحالية ديناميكيًا لتقييم الإمكانات الكامنة الكامنة في التوازي باستخدام تقنية SIMD، والتي يمكن استغلالها من خلال تطويرات إضافية للمترجمات و/أو عبر تغييرات يدوية في التعليمات البرمجية. [ 3 ]
التقنيات
مثال على ذلك برنامج لضرب متجهين من البيانات الرقمية. سيكون النهج القياسي على النحو التالي:
for ( i = 0 ; i < 1024 ; i ++ ) c [ i ] = a [ i ] * b [ i ];يمكن تحويل هذا إلى صيغة متجهة ليبدو كالتالي:
for ( i = 0 ; i < 1024 ; i += 4 ) c [ i : i + 3 ] = a [ i : i + 3 ] * b [ i : i + 3 ];هنا، يُمثل c[i:i+3] عناصر المصفوفة الأربعة من c[i] إلى c[i+3]، ويمكن لمعالج المتجهات تنفيذ أربع عمليات بتعليمات متجهة واحدة. وبما أن عمليات المتجهات الأربع تُنجز في نفس الوقت تقريبًا الذي تستغرقه تعليمة قياسية واحدة، فإن أسلوب المتجهات يُمكن أن يعمل بسرعة تصل إلى أربعة أضعاف سرعة الكود الأصلي.
هناك منهجان متميزان للمترجم: أحدهما يعتمد على تقنية التوجيه التقليدية والآخر يعتمد على فك الحلقات .
التحويل التلقائي إلى متجه على مستوى الحلقة
تحاول هذه التقنية، المستخدمة في آلات المتجهات التقليدية، إيجاد واستغلال التوازي في معالجة SIMD على مستوى الحلقة. وهي تتكون من خطوتين رئيسيتين كما يلي.
- ابحث عن حلقة داخلية يمكن تحويلها إلى متجه
- قم بتحويل الحلقة وإنشاء رموز متجهة
في الخطوة الأولى، يبحث المترجم عن العوائق التي قد تمنع التحويل إلى متجه. ومن أهم هذه العوائق وجود تبعية بيانات حقيقية أقصر من طول المتجه. وتشمل العوائق الأخرى استدعاءات الدوال وعدد التكرارات القصير.
بمجرد التأكد من إمكانية تحويل الحلقة إلى متجه، يتم تبسيطها باستخدام طول المتجه، ويتم استبدال كل تعليمة عددية داخل جسم الحلقة بتعليمات المتجه المقابلة. فيما يلي، توضح تحويلات المكونات لهذه الخطوة باستخدام المثال السابق.
- بعد التعدين السطحي
for ( i = 0 ; i < 1024 ; i += 4 ) for ( j = 0 ; j < 4 ; j ++ ) c [ i + j ] = a [ i + j ] * b [ i + j ];- توزيع ما بعد الحلقة باستخدام المصفوفات المؤقتة
for ( i = 0 ; i < 1024 ; i += 4 ) { for ( j = 0 ; j < 4 ; j ++ ) tA [ j ] = A [ i + j ]; for ( j = 0 ; j < 4 ; j ++ ) tB [ j ] = B [ i + j ]; for ( j = 0 ; j < 4 ; j ++ ) tC [ j ] = tA [ j ] * tB [ j ]; for ( j = 0 ; j < 4 ; j ++ ) C [ i + j ] = tC [ j ]; }- بعد استبدالها برموز متجهة
for ( i = 0 ; i < 1024 ; i += 4 ) { vA = vec_ld ( & A [ i ]); vB = vec_ld ( & B [ i ]); vC = vec_mul ( vA , vB ); vec_st ( vC , & C [ i ]); }التحويل التلقائي إلى مستوى الكتلة الأساسية
تستهدف هذه التقنية الحديثة نسبيًا على وجه التحديد بنى SIMD الحديثة ذات أطوال المتجهات القصيرة. [ 4 ] على الرغم من إمكانية فك الحلقات لزيادة مستوى التوازي في وحدات SIMD الأساسية، فإن هذه التقنية تستغل التوازي داخل الوحدات الأساسية نفسها بدلاً من الحلقات. وتتلخص الخطوتان الرئيسيتان فيما يلي.
- يتم فرد الحلقة الداخلية بمعامل طول المتجه لتشكيل جسم حلقة كبير.
- يتم تجميع التعليمات العددية المتماثلة (التي تؤدي نفس العملية) في تعليمات متجهة إذا لم تمنع التبعيات القيام بذلك.
ولإظهار التحولات خطوة بخطوة لهذا النهج، يتم استخدام المثال نفسه مرة أخرى.
- بعد فك الحلقة (بحسب طول المتجه، والذي يُفترض أنه 4 في هذه الحالة)
for ( i = 0 ; i < 1024 ; i += 4 ) { sA0 = ld ( & A [ i + 0 ]); sB0 = ld ( & B [ i + 0 ]); sC0 = sA0 * sB0 ; st ( sC0 , & C [ i + 0 ]); ... sA3 = ld ( & A [ i + 3 ]); sB3 = ld ( & B [ i + 3 ]); sC3 = sA3 * sB3 ; st ( sC3 , & C [ i + 3 ]); }- بعد التعبئة
for ( i = 0 ; i < 1024 ; i += 4 ) { ( sA0 , sA1 , sA2 , sA3 ) = ld ( & A [ i + 0 : i + 3 ]); ( sB0 , sB1 , sB2 , sB3 ) = ld ( & B [ i + 0 : i + 3 ]); ( sC0 , sC1 , sC2 , sC3 ) = ( sA0 , sA1 , sA2 , sA3 ) * ( sB0 , sB1 , sB2 , sB3 ); st (( sC0 , sC1 , sC2 , sC3 ), & C [ i + 0 : i + 3 ]); }- بعد إنشاء الكود
for ( i = 0 ; i < 1024 ; i += 4 ) { vA = vec_ld ( & A [ i ]); vB = vec_ld ( & B [ i ]); vC = vec_mul ( vA , vB ); vec_st ( vC , & C [ i ]); }هنا، تمثل sA1 و sB1 و ... متغيرات قياسية، وتمثل vA و vB و vC متغيرات متجهة.
تستخدم معظم المترجمات التجارية التي تقوم بالتحويل التلقائي إلى متجهات أسلوب مستوى الحلقة التقليدي باستثناء مترجم IBM XL، [ 5 ] الذي يستخدم كليهما.
في وجود تدفق التحكم
يتطلب وجود عبارات if في جسم الحلقة تنفيذ تعليمات في جميع مسارات التحكم لدمج القيم المتعددة لمتغير ما. يتمثل أحد الأساليب العامة في اتباع سلسلة من تحويلات الكود: التنبؤ ← التوجيه (باستخدام إحدى الطرق المذكورة أعلاه) ← إزالة مُسندات المتجهات ← إزالة مُسندات القيم العددية. [ 6 ] إذا تم استخدام الكود التالي كمثال لتوضيح هذه التحويلات؛
for ( i = 0 ; i < 1024 ; i ++ ) if ( A [ i ] > 0 ) C [ i ] = B [ i ]; else D [ i ] = D [ i -1 ];- بعد التنبؤ
for ( i = 0 ; i < 1024 ; i ++ ) { P = A [ i ] > 0 ; NP = ! P ; C [ i ] = B [ i ]; ( P ) D [ i ] = D [ i -1 ]; ( NP ) }حيث يشير (P) إلى مسند يحمي العبارة.
- بعد التحويل إلى متجه
for ( i = 0 ; i < 1024 ; i += 4 ) { vP = A [ i : i + 3 ] > ( 0 , 0 , 0 , 0 ); vNP = vec_not ( vP ); C [ i : i + 3 ] = B [ i : i + 3 ]; ( vP ) ( NP1 , NP2 , NP3 , NP4 ) = vNP ; D [ i + 3 ] = D [ i + 2 ]; ( NP4 ) D [ i + 2 ] = D [ i + 1 ]; ( NP3 ) D [ i + 1 ] = D [ i ]; ( NP2 ) D [ i ] = D [ i - 1 ]; ( NP1 ) }- بعد إزالة مسندات المتجهات
for ( i = 0 ; i < 1024 ; i += 4 ) { vP = A [ i : i + 3 ] > ( 0 , 0 , 0 , 0 ); vNP = vec_not ( vP ); C [ i : i + 3 ] = vec_sel ( C [ i : i + 3 ], B [ i : i + 3 ], vP ); ( NP1 , NP2 , NP3 , NP4 ) = vNP ; D [ i + 3 ] = D [ i + 2 ]; ( NP4 ) D [ i + 2 ] = D [ i + 1 ]; ( NP3 ) D [ i + 1 ] = D [ i ]; ( NP2 ) D [ i ] = D [ i - 1 ]; ( NP1 ) }- بعد إزالة المسندات العددية
for ( i = 0 ; i < 1024 ; i += 4 ) { vP = A [ i : i + 3 ] > ( 0 , 0 , 0 , 0 ); vNP = vec_not ( vP ); C [ i : i + 3 ] = vec_sel ( C [ i : i + 3 ], B [ i : i + 3 ], vP ); ( NP1 , NP2 , NP3 , NP4 ) = vNP ; if ( NP4 ) D [ i + 3 ] = D [ i + 2 ]; if ( NP3 ) D [ i + 2 ] = D [ i + 1 ]; if ( NP2 ) D [ i + 1 ] = D [ i ]; if ( NP1 ) D [ i ] = D [ i - 1 ]; }تقليل الحمل الزائد للتحويل إلى متجه في وجود تدفق التحكم
يُعدّ تنفيذ التعليمات في جميع مسارات التحكم في الشيفرة المتجهة أحد العوامل الرئيسية التي تُبطئ أداءها مقارنةً بالشيفرة العددية. فكلما ازداد تعقيد مسار التحكم، وزاد عدد التعليمات التي يتم تجاوزها في الشيفرة العددية، ازداد عبء التحويل إلى شيفرة متجهة. ولتقليل هذا العبء، يمكن إدراج فروع متجهة لتجاوز التعليمات المتجهة، على غرار كيفية تجاوز الفروع العددية للتعليمات العددية. [ 7 ] فيما يلي، تُستخدم مُسندات AltiVec لتوضيح كيفية تحقيق ذلك.
- خط الأساس القياسي (الكود الأصلي)
for ( i = 0 ; i < 1024 ; i ++ ) { if ( A [ i ] > 0 ) { C [ i ] = B [ i ]; if ( B [ i ] < 0 ) D [ i ] = E [ i ]; } }- بعد التوجيه في وجود تدفق التحكم
for ( i = 0 ; i < 1024 ; i += 4 ) { vPA = A [ i : i + 3 ] > ( 0 , 0 , 0 , 0 ); C [ i : i + 3 ] = vec_sel ( C [ i : i + 3 ], B [ i : i + 3 ], vPA ); vT = B [ i : i + 3 ] < ( 0 , 0 , 0 , 0 ); vPB = vec_sel (( 0 , 0 , 0 , 0 ), vT , vPA ); D [ i : i + 3 ] = vec_sel ( D [ i : i + 3 ], E [ i : i + 3 ], vPB ); }- بعد إدخال فروع المتجه
for ( i = 0 ; i < 1024 ; i += 4 ) { if ( vec_any_gt ( A [ i : i + 3 ], ( 0 , 0 , 0 , 0 ))) { vPA = A [ i : i + 3 ] > ( 0 , 0 , 0 , 0 ); C [ i : i + 3 ] = vec_sel ( C [ i : i + 3 ], B [ i : i + 3 ], vPA ); vT = B [ i : i + 3 ] < ( 0 , 0 , 0 , 0 ); vPB = vec_sel (( 0 , 0 , 0 , 0 ), vT , vPA ); if ( vec_any_ne ( vPB , ( 0 , 0 , 0 , 0 ))) D [ i : i + 3 ] = vec_sel ( D [ i : i + 3 ], E [ i : i + 3 ], vPB ); } }هناك أمران جديران بالملاحظة في الكود النهائي المتعلق بفروع المتجهات؛ أولًا، يتم تضمين تعليمة تعريف الشرط لـ vPA ضمن جسم فرع المتجه الخارجي باستخدام vec_any_gt. ثانيًا، تعتمد جدوى فرع المتجه الداخلي لـ vPB على الاحتمالية الشرطية لاحتواء vPB على قيم خاطئة في جميع الحقول، علمًا بأن vPA يحتوي على قيم خاطئة في جميع الحقول.
لنفترض مثالاً حيث يتم دائماً تنفيذ الفرع الخارجي في خط الأساس القياسي، متجاوزاً معظم التعليمات داخل جسم الحلقة. في الحالة الوسيطة المذكورة أعلاه، بدون فروع متجهة، يتم تنفيذ جميع التعليمات المتجهة. أما الكود النهائي، مع الفروع المتجهة، فينفذ كلاً من المقارنة والتفرع في وضع المتجهات، مما قد يحقق أداءً أفضل من خط الأساس القياسي.
معالجة المتجهات اليدوية
في معظم مُجمِّعات لغات C و C++ ، يُمكن استخدام الدوال المُضمَّنة لتطبيق SIMD يدويًا ، ولكن على حساب جهد المُبرمج، وسهولة الصيانة، وقابلية النقل. تتضمن بعض اللغات (مثل GNU C و C++ std::experimental::simdو Rust std::simd) أنواع بيانات متجهة تُجمَّع إلى تعليمات SIMD مُناسبة، مما يُحسِّن قابلية النقل ويُقلِّل الجهد المطلوب. [ 8 ]
هناك نهج آخر هو SPMD : كتابة برنامج يبدو وكأنه يتعامل مع عنصر واحد فقط في الوقت، ثم يقوم المترجم بتوسيعه ليتوافق مع عرض متجه SIMD. هذا هو النهج المستخدم في تظليل الرسومات، وقد اعتمدته مؤخرًا أدوات موجهة لوحدة المعالجة المركزية مثل Intel IPSC. على عكس التحويل التلقائي إلى متجهات، الذي قد يفشل ويعود إلى استخدام التعليمات البرمجية العددية (على سبيل المثال ، عند استدعاء دالة خارجية في حلقة تكرارية)، يضمن SPMD الحصول على تعليمات برمجية متجهة عند الاقتضاء، تمامًا مثل الاستخدام اليدوي للوظائف المضمنة أو أنواع بيانات المتجهات. [ 9 ]
انظر أيضاً
روابط خارجية
- صفحة مشروع التحويل التلقائي إلى متجهات لمترجم GCC
- توثيق التحويل التلقائي إلى المتجهات لمترجم Clang / LLVM
- دليل المطورين للتحويل التلقائي إلى متجهات لمترجم Intel C++ الكلاسيكي
مراجع
- ↑ بُذلت بعض الجهود لحل مشكلة استدعاء الدوال في شكل اصطلاحات استدعاء متجهة ومكتبات تستخدم هذه الاصطلاحات مثل libmvec . [ 2 ] : § تحويل استدعاءات الدوال إلى متجهات
- ↑ "ivdep" . Intel .
- 1 2 "التحويل التلقائي إلى متجه في LLVM — وثائق LLVM 23.0.0git" . llvm.org .
- ^ هولوينسكي، جوستين؛ رامامورثي، راجافيندار؛ رافيشانكار، ماهيش؛ فوزية، نازنين؛ بوشيت، لويس نويل؛ رونتيف، أتاناس؛ سادايابان ، ب. (6 أغسطس 2012). “التحليل الديناميكي القائم على التتبع لإمكانات توجيه التطبيقات”. إشعارات ACM SIGPLAN . 47 (6): 371-382 . دوى : 10.1145 / 2345156.2254108 .
- ↑ لارسن، س.؛ أماراسينغ، س. (2000). "استغلال التوازي على مستوى الكلمات الفائقة مع مجموعات تعليمات الوسائط المتعددة" . وقائع مؤتمر ACM SIGPLAN حول تصميم لغات البرمجة وتنفيذها. ACM SIGPLAN Notices . 35 (5): 145–156 . doi : 10.1145/358438.349320 . hdl : 1721.1/86445 .
- ↑ "تحسين الكود باستخدام مُجمِّعات IBM XL" (ملف PDF) . يونيو 2004. مؤرشف من الأصل (ملف PDF) بتاريخ 10-06-2010.
- ↑ شين، ج.؛ هول، م . و .؛ تشام، ج. (2005). "التوازي على مستوى الكلمات الفائقة في وجود تدفق التحكم". وقائع الندوة الدولية حول توليد الشفرة وتحسينها . ص 165-175 . doi : 10.1109/CGO.2005.33 . ISBN 0-7695-2298-X.
- ↑ شين، ج. (2007). "إدخال تدفق التحكم في التعليمات البرمجية المتجهة". وقائع المؤتمر الدولي السادس عشر حول الهندسة المعمارية المتوازية وتقنيات الترجمة . ص 280-291 . doi : 10.1109/PACT.2007.41 .
- ↑ "امتدادات المتجهات" . باستخدام مجموعة مترجمات جنو (GCC) . تم الاسترجاع في 16 يناير 2020 .
- ↑ فار، مات؛ مارك، ويليام ر. (مايو 2012). ispc: مُصرّف SPMD لبرمجة وحدة المعالجة المركزية عالية الأداء (ملف PDF) . مؤتمر الحوسبة المتوازية المبتكرة 2012 (InPar). الصفحات 1-13 . doi : 10.1109/InPar.2012.6339601 .
- تحسينات المُترجم
- الحوسبة المتوازية
- مشاكل الحوسبة الموزعة
- الحوسبة SIMD
