2017-07-25 58 views
0

我玩弄在GCC矢量instrinsics,特別是對AVX,和我很想寫這樣的事情做一個向量乘兩個陣列之間矢量內部函數:混疊規則排列在GCC

#include <unistd.h> 

void __attribute__((target("avx"))) vmul(float* __restrict__ cc, const float* __restrict__ aa, const float* __restrict__ bb, ssize_t size) { 
    const ssize_t VECSIZE=8; 
    typedef float vfloat __attribute__((vector_size(sizeof(float)*VECSIZE))); 

    // duff's device, process any remainder up front 
    ssize_t rem = size % VECSIZE; 
    switch (rem) { 
     case 7: cc[6] = aa[6]*bb[6]; /* FALLTHRU */ 
     case 6: cc[5] = aa[5]*bb[5]; /* FALLTHRU */ 
     case 5: cc[4] = aa[4]*bb[4]; /* FALLTHRU */ 
     case 4: cc[3] = aa[3]*bb[3]; /* FALLTHRU */ 
     case 3: cc[2] = aa[2]*bb[2]; /* FALLTHRU */ 
     case 2: cc[1] = aa[1]*bb[1]; /* FALLTHRU */ 
     case 1: cc[0] = aa[0]*bb[0]; /* FALLTHRU */ 
     case 0: break; 
    } 
    size -= rem; 

    // process rest of array 
    const vfloat *va = (const vfloat*)(aa+rem); 
    const vfloat *vb = (const vfloat*)(bb+rem); 
    vfloat *vc = (vfloat*)(cc+rem); 

    for (ssize_t ii=0; ii < size; ii++) { 
     vc[ii] = va[ii]*vb[ii]; 
    }  
} 

int main() { 
} 

問題是將數據導入向量類型所需的指針別名。海灣合作委員會高興地讓你這樣做(沒有警告 - 牆-Wextra -ansi -pedantic),但然後假定基礎內存對齊是適當的。因此,它產生在內部循環vmovaps說明:

0x0000000000400660 <+176>: vmovaps (%rsi,%rax,1),%ymm0 
    0x0000000000400665 <+181>: vmulps (%rdx,%rax,1),%ymm0,%ymm0 
    0x000000000040066a <+186>: vmovaps %ymm0,(%rdi,%rax,1) 
    0x000000000040066f <+191>: add $0x20,%rax 
    0x0000000000400673 <+195>: cmp %r8,%rax 
    0x0000000000400676 <+198>: jne 0x400660 <_Z4vmulPfPKfS1_l+176> 

這很好,直到你在一些非對齊的內存通過(或大小不是在我的案件8的倍數),然後興高采烈地出現segfaults您程序試圖用對齊的指令加載未對齊的內存。

有沒有適當的方法來做到這一點與矢量擴展?

回答

2

您可以reduce the alignment這樣的:

typedef float vfloat __attribute__((vector_size(sizeof(float)*VECSIZE), 
    aligned(4))); 

隨着這種變化,我得到vmovups指令。

+0

果然,似乎這樣做。我認爲這就是我需要的! –