2016-07-28 28 views
5

Hallo allerseits Ich versuche, das Intel-Spezifika zu verwenden, wie soProbleme mit Intel-Spezifika

void test() 
{ 
    uint16_t n1 = 5; 
    uint16_t n2 = 2; 
    __m64 vec1, vec2, res; 

    vec1 = _mm_set_pi16(n1, n1, n1, n1); 
    vec2 = _mm_set_pi16(n2, n2, n2, n2); 

    res = _mm_add_pi16(vec1, vec2); 

    printf("%u %u %u %u \n", vec1[0], vec1[1], vec1[2], vec1[3]); 
    printf("%u %u %u %u \n", vec2[0], vec2[1], vec2[2], vec2[3]); 
    printf("%u %u %u %u \n", res[0], res[1], res[2], res[3]); 
} 

aber die seltsame Sache, die ich erhalte diese Ergebnisse:

327685 327685 131074 131074 
131074 131074 458759 458759 
458759 458759 327685 327685 

ich benutze Eclipse Mars ... und ich schließe die mmintrin.h, xmmintrin.h, emmintrin.h.

Bitte kann mir jemand erklären, was diese falsch mit

+1

sollten Sie wahrscheinlich '__m128i' SSE Vektoren in neuem Code verwenden, nicht 64-Bit-MMX. Die SSE2-Unterstützung ist selbst in 32-Bit-Code als Baseline ziemlich sicher und für x86-64 garantiert. –

Antwort

5

Referenzieren __m64 als Array ist nicht Standard.
Ich weiß nicht, wie Ihr Compiler es behandelt.
Ich verwende den Intel Compiler in Visual Studio und erhalte einen Kompilierungsfehler. Sie sollten die Elemente uint16 aus dem MMX-Register in das ALU-Register extrahieren, bevor Sie drucken.
Verwenden Sie _mm_extract_pi16 intrinsic, um den Wert zu extrahieren.

Vergessen Sie nicht, die intrinsische Funktion _mm_empty() aufzurufen, bevor Sie die Funktion beenden.

Siehe das folgende Codebeispiel:

#include <stdint.h> 
#include <stdio.h> 

#include <mmintrin.h> 
#include <xmmintrin.h> 
#include <emmintrin.h> 

static void Test() 
{ 
    uint16_t n1=5; 
    uint16_t n2=2; 
    __m64 vec1,vec2,res; 

    vec1 = _mm_set_pi16 (n1 ,n1 ,n1 ,n1); 
    vec2 = _mm_set_pi16 (n2 ,n2 ,n2 ,n2); 

    res = _mm_add_pi16 (vec1, vec2); 

    //uint16_t res0 = _mm_extract_pi16(res, 0); 
    //uint16_t res1 = _mm_extract_pi16(res, 1); 
    //uint16_t res2 = _mm_extract_pi16(res, 2); 
    //uint16_t res3 = _mm_extract_pi16(res, 3); 

    printf("%u %u %u %u \n",_mm_extract_pi16(vec1, 0),_mm_extract_pi16(vec1, 1),_mm_extract_pi16(vec1, 2),_mm_extract_pi16(vec1, 3)); 
    printf("%u %u %u %u \n",_mm_extract_pi16(vec2, 0),_mm_extract_pi16(vec2, 1),_mm_extract_pi16(vec2, 2),_mm_extract_pi16(vec2, 3)); 
    printf("%u %u %u %u \n",_mm_extract_pi16(res, 0),_mm_extract_pi16(res, 1),_mm_extract_pi16(res, 2),_mm_extract_pi16(res, 3)); 

    _mm_empty(); 
} 

int main() 
{ 
    Test(); 

    return 0; 
} 

Ausgang:

 
5 5 5 5 
2 2 2 2 
7 7 7 7 
+1

IIRC, die ABI erfordert, dass die FPU bei Funktionsaufrufen im x87-Zustand ist. Sie sollten also '_mm_empty()' vor dem Aufruf von printf aufrufen. Das OP würde dieses Problem nicht haben, wenn sie SSE anstelle von veraltetem MMX verwenden. –

+0

MMX gehören zu den 90ern, du musst SSE benutzen ... Auch wenn es nur für akademische Zwecke ist ... bitte benutze SSE !!! – Rotem

3

Lassen Sie uns diese Werte in hexadezimale Zeichenketten konvertieren:

0x00050005 0x00050005 0x00020002 0x00020002 
0x00020002 0x00020002 0x00070007 0x00070007 
0x00070007 0x00070007 0x00050005 0x00050005 

Es scheint, dass der Compiler nicht die übliche Integral Promotions auf eine indizierte __m64 Variable Anwendung, so dass jeder übergebene Wert 16 Bits des Parameterraums verbraucht (wahrscheinlich auf dem Stack), und dann printf 32 Bits für jede %u dekodiert.

Sie sollten mit expliziten Abgüsse dieses Problem beheben können, wie:

printf("%u %u %u %u \n", (unsigned int)vec1[0], (unsigned int)vec1[1], 
         (unsigned int)vec1[2], (unsigned int)vec1[3]); 

Integral Aktionen sollen Parameter von variadische Funktionen angewendet werden ... aber wenn das Ergebnis hier von Indizierung nicht genau ist ein der Integraltypen gilt diese Regel nicht mehr.

+0

Also, wie kann ich es beheben? irgendeine Idee ? Das Problem ist das gleiche mit ** _ mm_set_pi8 ** und ** _ mm_add_pi16 ** aber es funktioniert für 32 –

+0

@ A.nechi: Das Problem besteht nur darin, Werte zu printf() 'zur Anzeige zu übergeben ... die Berechnungen werden richtig gemacht. Sie können die Anzeige korrigieren, indem Sie genau auf den Typ 'printf()' klicken. –