gpt4 book ai didi

c - 由于内存对齐不正确,使用 SSE 内部函数时出现段错误

转载 作者:太空狗 更新时间:2023-10-29 17:19:20 25 4
gpt4 key购买 nike

我是第一次使用 SSE 内在函数,即使在确保 16 字节内存对齐后我仍遇到段错误。这篇文章是对我之前问题的扩展:

How to allocate 16byte memory aligned data

这是我声明数组的方式:

  float *V = (float*) memalign(16,dx*sizeof(float));

当我尝试这样做时:

  __m128 v_i = _mm_load_ps(&V[i]); //It works

但是当我这样做的时候:

  __m128 u1 = _mm_load_ps(&V[(i-1)]); //There is a segmentation fault

但如果我这样做:

  __m128 u1 = _mm_loadu_ps(&V[(i-1)]); //It works again

但是我想消除使用 _mm_loadu_ps 并希望仅使用 _mm_load_ps 使其工作。

我正在使用英特尔 icc 编译器。

我该如何解决这个问题?

更新:

在以下代码中使用这两个操作:

  void FDTD_base (float *V, float *U, int dx, float c0, float c1, float c2, float c3,     float c4)
{
int i, j, k;
for (i = 4; i < dx-4; i++)
{

U[i] = (c0 * (V[i]) //center
+ c1 * (V[(i-1)] + V[(i+1)] )
+ c2 * (V[(i-2)] + V[(i+2)] )
+ c3 * (V[(i-3)] + V[(i+3)] )
+ c4 * (V[(i-4)] + V[(i+4)] ));
}

}

上海证券交易所版本:

         for (i=4; i < dx-4; i+=4)
{
v_i = _mm_load_ps(&V[i]);
__m128 center = _mm_mul_ps(v_i,c0_i);

__m128 u1 = _mm_loadu_ps(&V[(i-1)]);
u2 = _mm_loadu_ps(&V[(i+1)]);

u3 = _mm_loadu_ps(&V[(i-2)]);
u4 = _mm_loadu_ps(&V[(i+2)]);

u5 = _mm_loadu_ps(&V[(i-3)]);
u6 = _mm_loadu_ps(&V[(i+3)]);

u7 = _mm_load_ps(&V[(i-4)]);
u8 = _mm_load_ps(&V[(i+4)]);

__m128 tmp1 = _mm_add_ps(u1,u2);
__m128 tmp2 = _mm_add_ps(u3,u4);
__m128 tmp3 = _mm_add_ps(u5,u6);
__m128 tmp4 = _mm_add_ps(u7,u8);

__m128 tmp5 = _mm_mul_ps(tmp1,c1_i);
__m128 tmp6 = _mm_mul_ps(tmp2,c2_i);
__m128 tmp7 = _mm_mul_ps(tmp3,c3_i);
__m128 tmp8 = _mm_mul_ps(tmp4,c4_i);

__m128 tmp9 = _mm_add_ps(tmp5,tmp6);
__m128 tmp10 = _mm_add_ps(tmp7,tmp8);

__m128 tmp11 = _mm_add_ps(tmp9,tmp10);
__m128 tmp12 = _mm_add_ps(center,tmp11);

_mm_store_ps(&U[i], tmp12);
}

是否有仅使用 _mm_load_ps() 更有效的方法?

最佳答案

sizeof(float)是 4,只有 V 中的每四个条目将正确对齐。请记住 _mm_load_ps一次加载四个 float 。参数,即指向第一个 float 的指针,需要对齐到 16 个字节。

我假设在你的例子中 i是四的倍数,否则 _mm_load_ps(&V[i])会失败。

更新

这就是我建议使用对齐加载和随机播放实现上述滑动窗口示例的方式:

__m128 v_im1;
__m128 v_i = _mm_load_ps( &V[0] );
__m128 v_ip1 = _mm_load_ps( &V[4] );

for ( i = 4 ; i < dx ; i += 4 ) {

/* Get the three vectors in this 'frame'. */
v_im1 = v_i; v_i = v_ip1; v_ip1 = _mm_load_ps( &V[i+4] );

/* Get the u1..u8 from the example code. */
__m128 u3 = _mm_shuffle_ps( v_im1 , v_i , 3 + (4<<2) + (0<<4) + (1<<6) );
__m128 u4 = _mm_shuffle_ps( v_i , v_ip1 , 3 + (4<<2) + (0<<4) + (1<<6) );

__m128 u1 = _mm_shuffle_ps( u3 , v_i , 1 + (2<<2) + (1<<4) + (2<<6) );
__m128 u2 = _mm_shuffle_ps( v_i , u4 , 1 + (2<<2) + (1<<4) + (2<<6) );

__m128 u5 = _mm_shuffle_ps( v_im1 , u3 , 1 + (2<<2) + (1<<4) + (2<<6) );
__m128 u6 = _mm_shuffle_ps( u4 , v_ip1 , 1 + (2<<2) + (1<<4) + (2<<6) );

__m128 u7 = v_im1;
__m128 u8 = v_ip1;

/* Do your computation and store. */
...

}

请注意,这有点棘手,因为 _mm_shuffle_ps只能从每个参数中取两个值,这就是为什么我们首先需要制作 u3u4以便将它们重新用于具有不同重叠的其他值。

另请注意值 u1 , u3 , 和 u5也可以从 u2 中恢复, u4u6在之前的迭代中。

请注意,最后,我没有验证上面的代码!阅读 _mm_shuffle_ps 的文档并检查第三个参数,即选择器,对于每种情况都是正确的。

关于c - 由于内存对齐不正确,使用 SSE 内部函数时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11085924/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com