对齐AVX操作的双重对齐浮点

时间:2016-05-25 09:19:53

标签: c++ memory-alignment avx

我想将两个(浮点/双)矢量与AVX运算符相乘。为了做到这一点,我需要对齐记忆。我的浮点值函数是:

#define SIZE 65536
float *g, *h, *j;
g = (float*)aligned_alloc(32, sizeof(float)*SIZE);
h = (float*)aligned_alloc(32, sizeof(float)*SIZE);
j = (float*)aligned_alloc(32, sizeof(float)*SIZE);
//Filling g and h with data
for(int i = 0; i < SIZE/8; i++)
    {
        __m256 a_a, b_a, c_a;
        a_a = _mm256_load_ps(g+8*i);
        b_a = _mm256_load_ps(h+8*i);
        c_a = _mm256_mul_ps(a_a, b_a);
        _mm256_store_ps (j+i*8, c_a);
    }
free(g);
free(h);
free(j);

这样可行,但是当我尝试使用double值时,我会收到内存访问错误(例如内存未正确对齐):

double *g_d, *h_d, *i_d;
g_d = (double*)aligned_alloc(32, sizeof(double)*SIZE);
h_d = (double*)aligned_alloc(32, sizeof(double)*SIZE);
i_d = (double*)aligned_alloc(32, sizeof(double)*SIZE);
for(int i = 0; i < SIZE/4; i++)
{
    __m256d a_a, b_a, c_a;
    a_a = _mm256_load_pd(g_d+4*i);
    b_a = _mm256_load_pd(h_d+4*i);
    c_a = _mm256_mul_pd(a_a, b_a);
    _mm256_store_pd (i_d+i*4, c_a);
}
free(g_d);
free(h_d);
free(i_d);

为什么对齐不适用于double - 值?

在gdb中运行时,我得到了

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401669 in _mm256_load_pd (__P=0x619f70) at /usr/lib/gcc/x86_64-linux-gnu/5/include/avxintrin.h:836

编辑:我发现了我的错误,它是来自前一个函数的复制/粘贴错误,表现在该函数中。由于对其他人没有帮助(正如我所假设的),我提出了这个问题。

1 个答案:

答案 0 :(得分:0)

好吧,您的问题似乎源于不同的数据大小。

  • 在第一个代码段中,将float循环增加到SIZE/8 = 8192。在这里,我不确定为什么要增加元素大小为4的FLOAT数组。所以i < 8192
  • 在第二个代码段中,您将double循环增加到SIZE/4 = 16384。在这里,我不确定为什么要增加元素大小为8的DOUBLE数组。所以i < 16384 --- **相反!**

DOUBLE数组的最后一个元素可能会超越你的内存边界!

在这两种情况下,您都可以使用i++增加循环次数。案件如下:

首先:(FLOAT(4))j + i * 8(0&lt; i&lt; 8192)=&gt;

0      4      8      12      16     20     24     28  
v1     .      v2     .       v3     .      v4     . 

第二:( DOUBLE(8))j + i * 4(0&lt; i&lt; 16384)=&gt; V1 / V2 / V3 / V4

0      4      8      12      16     20     24     28     32  
v1(h)  v1(l)  v2(l)  v3(l)   v4(l)  v5(l)  v6(l)  v7(l) 
v1(h)  v2(h)  v3(h)  v4(h)   v5(h)  v6(h)  v7(h)  v8(h)  v8(h)
--------------------------------------------------------------
some thing ... some thing ... some thing .. some thing ...

在第二个片段中,您将64位Double的高部分(32位)和低部分(32位)混合为仅增加4(sizeof FLOAT)而不是8(sizeof DOUBLE)。

另一个问题是_mm256_store_pd要求......

  

当源或目标操作数是内存操作数时,操作数必须在32字节边界上对齐,否则将生成一般保护异常(#GP)。

for(int i = 0; i < SIZE/4; i++)无法满足此要求。

我想知道您的FLOAT版本似乎有效,因为_mm256_store_ps要求... {/ p>

  

当源或目标操作数是内存操作数时,操作数必须在16字节边界上对齐,否则将生成一般保护异常(#GP)。

但你只有8个字节的对齐...

但是,您需要修复&#39;比例尺。您的i变量可以使其发挥作用。