سؤال

أنا أستخدم SIMD لحساب نتيجة الأسس السريعة. أقارن التوقيت مع رمز غير SIMD. يتم تنفيذ الأسس باستخدام خوارزمية مربعة وضرب.

نسخة عادية (غير SIMD) من الكود:

b = 1;  
for (i=WPE-1; i>=0; --i){  
    ew = e[i];  
    for(j=0; j<BPW; ++j){  
        b = (b * b) % p;  
        if (ew & 0x80000000U)  b = (b * a) % p;  
        ew <<= 1;  
    }  
}  

نسخة SIMD:

   B.data[0] = B.data[1] = B.data[2] = B.data[3] = 1U;  
   P.data[0] = P.data[1] = P.data[2] = P.data[3] = p;  
   for (i=WPE-1; i>=0; --i) {  
      EW.data[0] = e1[i]; EW.data[1] = e2[i]; EW.data[2] = e3[i]; EW.data[3] = e4[i];  
      for (j=0; j<BPW;++j){  
         B.v *= B.v; B.v -= (B.v / P.v) * P.v;  
         EWV.v = _mm_srli_epi32(EW.v,31);  
         M.data[0] = (EWV.data[0]) ? a1 : 1U;  
         M.data[1] = (EWV.data[1]) ? a2 : 1U; 
         M.data[2] = (EWV.data[2]) ? a3 : 1U; 
         M.data[3] = (EWV.data[3]) ? a4 : 1U;  
         B.v *= M.v; B.v -= (B.v / P.v) * P.v;  
         EW.v = _mm_slli_epi32(EW.v,1);  
      }  
   } 

تكمن المشكلة في الحوسبة بشكل صحيح ، فإن إصدار SIMD يستغرق وقتًا أطول من الإصدار غير SIMD.

الرجاء مساعدتي تصحيح الأسباب. أي اقتراحات بشأن ترميز SIMD مرحب بها أيضًا.

شكرا وتحياتي ، anup.

هل كانت مفيدة؟

المحلول

يجب أن تكون جميع الوظائف في الحلقات من وظائف SIMD ، وليس فقط. الوقت الذي يستغرقه تعيين الوسيطات لوظائفك 2 أقل مثالًا ثم مثالك الأصلي (والذي يحتمل أن يكون على الأرجح محسّنًا بواسطة برنامج التحويل البرمجي)

نصائح أخرى

عادةً ما تبدو حلقة SIMD لبيانات int 32 بت عادة مثل هذا:

for (i = 0; i < N; i += 4)
{
    // load input vector(s) with data at array index i..i+3
    __m128 va = _mm_load_si128(&A[i]);
    __m128 vb = _mm_load_si128(&B[i]);

    // process vectors using SIMD instructions (i.e. no scalar code)
    __m128 vc = _mm_add_epi32(va, vb);

    // store result vector(s) at array index i..i+3
    _mm_store_si128(&C[i], vc);
}

إذا وجدت أنك بحاجة إلى التحرك بين الرمز القياسي ورمز SIMD داخل الحلقة ، فربما لن تحصل على أي شيء من تحسين SIMD.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top