2016-07-28 18 views
5

Witam wszystkich Próbuję użyć intrinsics intel jak takProblemy z intrinsics intel

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]); 
} 

ale dziwne, że jestem coraz to wyniki:

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

używam Zaćmienie Marsa ... i włączam w to , xmmintrin.h, emmintrin.h.

Proszę może ktoś wyjaśnić, co się stało z tym

+1

Należy prawdopodobnie używając '__m128i' wektory SSE w nowym kodem, a nie 64-bitowy MMX. Obsługa SSE2 jest całkiem bezpieczna, aby założyć ją jako linię podstawową, nawet w 32-bitowym kodzie, i jest gwarantowana dla x86-64. –

Odpowiedz

5

Odwołanie __m64 ponieważ tablica jest niestandardowa.
Nie wiem, jak to robi Twój kompilator.
Używam kompilatora Intel w Visual Studio i pojawia się błąd kompilacji. Należy wyodrębnić elementy uint16 z rejestru MMX do rejestru ALU przed drukowaniem.
Użyj wewnętrznego, aby wyodrębnić wartość.

Nie zapomnij zadzwonić pod numer wewnętrzny _mm_empty() przed wyjściem z funkcji.

Zobacz następujący przykładowy kod:

#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; 
} 

wyjściowa:

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

IIRC, ABI wymaga, aby jednostka FPU znajdowała się w stanie x87 przy wywołaniach funkcji. Więc powinieneś '_mm_empty()' przed wywołaniem printf. OP nie miałby tego problemu, gdyby używał SSE zamiast przestarzałego MMX. –

+0

MMX należą do lat 90-tych, należy użyć SSE ... Nawet jeśli jest to tylko do celów akademickich ... proszę użyć SSE !!! – Rotem

3

Niech przekonwertować te wartości do ciągów szesnastkowych:

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

Wydaje się, że kompilator nie ubiega się zwykle integralne promocjach na dolnym lub __m64 zmiennej, więc każda przekazywana wartość zużywa 16 bitów przestrzeni parametru (prawdopodobnie na stosie), a następnie printf dekoduje 32 bity dla każdego %u.

powinien być w stanie rozwiązać ten problem z wyraźnymi odlewów, jak:

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

Integral promocje mają być stosowane do parametrów funkcji o zmiennej liczbie argumentów ... ale jeśli wynik indeksowanie tutaj nie jest dokładnie jeden typów integralnych, wówczas ta reguła przestaje obowiązywać.

+0

Jak mogę to naprawić? dowolny pomysł ? Problem jest taki sam w przypadku ** _ mm_set_pi8 ** i ** _ mm_add_pi16 **, ale działa dla 32 –

+0

@ A.nechi: Problem występuje tylko w przekazywaniu wartości do 'printf()' dla wyświetlania ... obliczenia są zrobione dobrze. Możesz naprawić wyświetlacz, przesyłając go do żądanego rodzaju 'printf()' chce. –