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您程序试图用对齐的指令加载未对齐的内存。
有没有适当的方法来做到这一点与矢量扩展?
果然,似乎这样做。我认为这就是我需要的! –