2014-07-14 31 views
2

這段代碼(加倍4-向量)的工作原理:添加兩個4-向量與SSE使用指針

__declspec(align(16)) struct vec4 { float a[4]; }; 

int main() 
{ 
    vec4 c; 
    c.a[0]=2; 
    c.a[1]=0; 
    c.a[2]=0; 
    c.a[3]=0; 

    __asm { 
     movaps xmm1, c 

     addps xmm1, xmm1 
     movaps c, xmm1 
    } 
} 

但這件(做同樣的,但現在用的指針對準的數據)沒有按't:

__declspec(align(16)) struct vec4 { float a[4]; }; 

int main() 
{ 
    vec4* c = new vec4; 
    c->a[0]=2; 
    c->a[1]=0; 
    c->a[2]=0; 
    c->a[3]=0; 

    __asm { 
     movaps xmm1, c 

     addps xmm1, xmm1 
     movaps c, xmm1 
    } 
} 

爲什麼?

我需要它來處理指針,因爲我不能使用對齊數據本身作爲函數參數。

+1

你爲什麼不使用SSE內在函數?只是想知道...我不寫SSE代碼。 – rubenvb

+2

顯然,相同的代碼不能適用於這兩種情況,因爲它們的間接級別不同。你必須首先將指針加載到一個寄存器中,然後使用另一個間接指針。例如,'mov eax,c; movaps xmm1,[eax]'... – Jester

+0

當編寫一個更復雜的矢量化算法時,當寄存器壓力增加時,通常有太多東西進出寄存器,我可以通過編寫它在自己的組裝中。 – renger

回答

0

ASM中的指針必須按照某些規則處理,您可以通過學習how "MOV" works來學習。按照彙編程序的規則,你首先需要將指針複製到cpu寄存器。那麼你可以用它來指向內存位置。

vec4 *d = ...; 
__asm { 
    mov eax, d 
    movaps xmm1, [eax] 

    addps xmm1, xmm1 
    movaps [eax], xmm1 
} 
0

問題是由堆分配器(如new和malloc)創建的對象不遵循您指定的對齊方式。你只能得到你的堆棧分配對象(你的第一個例子)。

C++ 11支持使用alignas通過堆分配的對象的顯式對齊,但這還沒有通過VC++實現。它將與一些編譯器一起工作,而不是其他的。

您有幾個選項。

最簡單的一個:創建堆上分配對象,你做到了,在使用前將其複製到堆棧中分配對象:

vec4* c = new vec4; 
c->a[0]=2; 
c->a[1]=0; 
c->a[2]=0; 
c->a[3]=0; 

vec4 d = *c; 
// process with d 

另一種選擇是讓你vec4結構包括足夠額外的內存,這樣你就可以保證16字節對齊時有16個字節。我相信新的保證至少有4個字節對齊,所以28個字節就可以了。然後,您必須手動檢查指針,以查看要存儲要用於sse的數據的位置。