كيفية تحويل تعويم سداسي إلى تعويم في C/C ++ باستخدام وظيفة instrinc

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

سؤال

أنا أكتب رمز SSE إلى الالتفاف ثنائي الأبعاد ولكن وثائق SSE متناثرة للغاية. أقوم بحساب منتج DOT باستخدام _mm_dp_ps وأستخدم _mm_extract_ps للحصول على نتيجة منتج DOT ، ولكن _mm_extract_ps يرجع سداسي يمثل تعويمًا ولا يمكنني معرفة كيفية تحويل هذا العائمة السداسية إلى تعويم منتظم. يمكنني استخدام __BUILTIN_IA32_VEC_EXT_V4SF الذي يعيد تعويمًا ولكني أريد الحفاظ على التوافق مع المترجمين الآخرين.

_mm_extract_ps (__m128 __X, const int __N)
{
  union { int i; float f; } __tmp;
  __tmp.f = __builtin_ia32_vec_ext_v4sf ((__v4sf)__X, __N);
  return __tmp.i;
}

ما النقطة التي أفتقدها؟

سيتم تقدير القليل من المساعدة ، شكرًا.

Opensuse 11.2
GCC 4.4.1
C ++
خيارات المترجم
-fopenmp -wal -o3 -msse4.1 -march = core2
خيارات الرابط
-lgomp -wall -o3 -msse4.1 -March = core2

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

المحلول

يجب أن تكون قادرًا على الاستخدام _MM_EXTRACT_FLOAT.

بالمناسبة يبدو لي كما لو _mm_extract_ps و _MM_EXTRACT_FLOAT يجب أن يكون العكس ، أي _mm_extract_ps يجب أن تعيد تعويم و _MM_EXTRACT_FLOAT يجب أن تعيد تمثيل INT ، لكن ماذا أعرف.

نصائح أخرى

_mm_cvtss_f32(_mm_shuffle_ps(__X, __X, __N)) سوف تفعل المهمة.

ومجرد تجسيد كل ما تم ذكره حتى الآن:

ج الرئيسية

#include <assert.h>

#include <x86intrin.h>

int main(void) {

    /* 32-bit. */
    {
        __m128 x = _mm_set_ps(1.5f, 2.5f, 3.5f, 4.5f);

        /* _MM_EXTRACT_FLOAT */
        float f;
        _MM_EXTRACT_FLOAT(f, x, 3);
        assert(f == 1.5f);
        _MM_EXTRACT_FLOAT(f, x, 2);
        assert(f == 2.5f);
        _MM_EXTRACT_FLOAT(f, x, 1);
        assert(f == 3.5f);
        _MM_EXTRACT_FLOAT(f, x, 0);
        assert(f == 4.5f);

        /* _mm_cvtss_f32 + _mm_shuffle_ps */
        assert(_mm_cvtss_f32(x) == 4.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 1)) == 3.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 2)) == 2.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 3)) == 1.5f);
    }

    /* 64-bit. */
    {
        __m128d x = _mm_set_pd(1.5, 2.5);
        /* _mm_cvtsd_f64 + _mm_unpackhi_pd */
        assert(_mm_cvtsd_f64(x) == 2.5);
        assert(_mm_cvtsd_f64(_mm_unpackhi_pd(x, x)) == 1.5);
    }
}

Github upstream.

تجميع وتشغيل:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

الزوجي المذكورة في: _MM_CVTSD_F64 ALANGON للحصول على نقطة عائمة أعلى ترتيب

تم اختباره على Ubuntu 19.04 AMD64.

extern void _mm_store_ss (float*، __m128) ؛

انظر "xmmintrin.h."

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