ما هي الطريقة الأكثر فعالية لمضاعفة 4 عوامات بنسبة 4 عوامات باستخدام SSE؟

StackOverflow https://stackoverflow.com/questions/1227249

  •  22-07-2019
  •  | 
  •  

سؤال

وأنا حاليا التعليمة البرمجية التالية:

float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };
asm volatile("movups (%0), %%xmm0\n\t"
             "mulps (%1), %%xmm0\n\t"             
             "movups %%xmm0, (%1)"             
             :: "r" (a), "r" (b));

ولدي أولا وقبل كل بضعة أسئلة:

و(1) إذا كان لي أن محاذاة صفائف على حدود 16 بايت، فإنه حتى تعمل؟ منذ يتم تخصيص صفائف على كومة هل صحيح ان مواءمتها هو شبه مستحيل؟

وانظر جواب اختيارها لهذا المنصب: هل المتغيرات كومة الانحياز من قبل __ __attribute دول مجلس التعاون الخليجي ((محاذاة (خ)) )؟

و(2) هل يمكن ريفاكتوريد رمز على الإطلاق لجعله أكثر كفاءة؟ ماذا لو أنني وضعت كل من صفائف تطفو في سجلات بدلا من واحدة فقط؟

والشكر

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

المحلول

<اقتباس فقرة>   

وإذا كنت لمحاذاة صفائف على حدود 16 بايت، فإنه حتى تعمل؟ منذ يتم تخصيص صفائف على كومة هل صحيح ان مواءمتها هو شبه مستحيل؟

ومطلوب أن التوافق على كومة تعمل. إلا أن intrinsics لا تعمل. اعتقد ان هذا المنصب نقلت لكم لا علاقة لها قيمة باهظة اختياره لقيمة المحاذاة.

ل2:

لا، لا ينبغي أن يكون هناك اختلاف في الأداء. انظر هذا الموقع عن توقيت تعليمات من عدة معالجات.


وكيف التوفيق بين المتغيرات كومة تعمل:

push    ebp
mov ebp, esp
and esp, -16                ; fffffff0H
sub esp, 200                ; 000000c8H

و <م> و بمحاذاة تبدأ من المكدس إلى 16 بايت.

نصائح أخرى

واكتب في C، استخدم

gcc -S -mssse3

وإذا كان لديك نسخة حديثة نسبيا من دول مجلس التعاون الخليجي.

<اقتباس فقرة>   

و(1) إذا كنت لمحاذاة صفائف في 16 حدود بايت، فإنه حتى تعمل؟ منذ يتم تخصيص صفائف على كومة هل صحيح ان مواءمتها هو شبه مستحيل؟

لا، انها بسيطة جدا لمحاذاة مؤشر مكدس باستخدام and:

and esp, 0xFFFFFFF0 ; aligned on a 16-byte boundary

ولكن يجب استخدام ما يوفر دول مجلس التعاون الخليجي، مثل نوع 16 بايت، أو __attribute__ لتخصيص المحاذاة.

هل تقدم دول مجلس التعاون الخليجي دعما لنوع البيانات __m128؟ إذا كان الأمر كذلك وهذا أفضل خطتك لضمان 16 بايت محاذاة نوع البيانات. ومع ذلك هناك __attribute__((aligned(16))) لمواءمة الأشياء. تحديد المصفوفات كما يلي

float a[4] __attribute__((aligned(16))) = { 10, 20, 30, 40 };
float b[4] __attribute__((aligned(16))) = { 0.1, 0.1, 0.1, 0.1 };

ومن ثم استخدام movaps بدلا من ذلك:)

وعن طريق جوهري هو أسرع بكثير خصوصا مع الأمثل. كتبت اختبار بسيط ومقارنة كل نسخة (ASM وجوهري)

unsigned long long time1;
__m128 a1,b1;


a1=_mm_set_ps(10, 20,30,40);
b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);
float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };

time1=__rdtsc();
a1=_mm_mul_ps(a1,b1);
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);


time1=__rdtsc();
asm volatile("movups (%0), %%xmm0\n\t"
                 "mulps (%1), %%xmm0\n\t"
                 "movups %%xmm0, (%1)"
                 :: "r" (a), "r" (b));
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);

والجوهرية النسخة 50-60 الطوابع معالج عصم النسخة ~ 1000 الطوابع بروك

ويمكنك اختبار على جهازك

وعن إعادة بيع ديون. يمكنك استخدام جوهري. مثال:

#include <emmintrin.h>

int main(void)
{
    __m128 a1,b1;

    a1=_mm_set_ps(10, 20,30,40);
    b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);

    a1=_mm_mul_ps(a1,b1);

    return 0;
}

ومع دول مجلس التعاون الخليجي الأمثل (-O2، -O3) قد يكون العمل بشكل أسرع ثم ASM.

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