2016-07-28 89 views
5

大家好,我嘗試使用英特爾內部函數,像這樣問題與英特爾內在

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

但奇怪的事情,我得到這個結果:

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

我使用日食火星......並且我包括mmintrin.h,xmmintrin.h,emmintrin.h

請某人能解釋什麼不對的

+1

你或許應該使用'__m128i'上證所在新代碼矢量,而不是64位MMX。即使在32位代碼中,SSE2支持也可以作爲基準很安全,並且可以保證x86-64。 –

回答

5

參考__m64由於數組是非標準的。
我不知道你的編譯器如何處理它。
我在Visual Studio中使用英特爾編譯器,並得到編譯錯誤。 在打印之前,您應該將MMX寄存器中的uint16元素提取到ALU寄存器。
使用_mm_extract_pi16固有提取值。

不要忘記在退出函數之前調用_mm_empty()內部函數。

請看下面的代碼示例:

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

輸出:

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

IIRC,ABI要求FPU在函數調用中處於x87狀態。所以你應該在調用printf之前調用_mm_empty()。如果他們使用SSE而不是過時的MMX,OP將不會有這個問題。 –

+0

MMX屬於90年代,你必須使用SSE ...即使它只是爲了學術目的...請使用SSE! – Rotem

3

讓我們這些值轉換爲十六進制字符串:

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

看來,編譯器不採用通常的整體促銷活動的下標__m64變量,因此您傳遞的每個值都消耗16位參數空間(可能在堆棧中),然後printf正在爲每個%u解碼32位。

你應該能夠用顯式轉換解決這個問題,比如:

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

積分促銷活動應該被應用到的可變參數函數的參數...但如果下標在這裏的結果是不完全的一個的整數類型,那麼該規則不再適用。

+0

那麼,我該如何解決它?任何想法 ?問題與** _ mm_set_pi8 **和** _ mm_add_pi16 **相同​​,但它的工作原理爲32 –

+0

@ A.nechi:問題僅在於將值傳遞給'printf()以供顯示...計算正在做對了。您可以通過轉換爲'printf()'所需的確切類型來修復顯示。 –