SSE _mm_store_ps 分段错误问题

Posted

技术标签:

【中文标题】SSE _mm_store_ps 分段错误问题【英文标题】:SSE _mm_store_ps Segmentation fault issues 【发布时间】:2014-02-13 00:34:59 【问题描述】:

我在使用 _mm_store_ps 命令时遇到问题。我在使用它时遇到了分段错误(我知道这是问题所在,因为当我注释掉该行时,分段错误消失了)。不过这很奇怪,因为我使用的是一个静态数组,我手动要求编译器对齐,并且使用 _mm_storeu_ps 不会使问题消失。这是相关的代码部分:

//Directly access array instead of using Boost interface
boost::numeric::ublas::matrix<float>::iterator2 it = result.begin2();
float temp[4] __attribute__((aligned__(16))), temp2 = 0;

//Use SSE
__m128 m1, sse_right1, sse_left1, store_sse __attribute__((aligned (16))) = _mm_set_ps1(0);

unsigned k = 0;
//Iterate over the dimensions of the matrices
for (unsigned i = 0; i < ls1; i++)
   
    for (unsigned j = 0; j < rs2; j++)
       
        while (k + 3 < ls2)
           
            sse_right1 = _mm_load_ps(arr + k + j * rs1); 
            sse_left1 = _mm_load_ps(left_arr + k + i * ls2);
            m1 = _mm_mul_ps(sse_right1, sse_left1);
            store_sse = _mm_add_ps(store_sse,m1);
            k += 4;
           

        //If ls2 isn't divisible by 4
        while (k < ls2)
           
            temp2 += left_arr[i * ls2 + k] * arr[k + j * rs1];
            k++;
           

        if (ls2 >= 4)
           
            _mm_store_ps(temp, store_sse);

            for (unsigned l = 0; l < 4; l++)
               
                temp2 += temp[l];
               
           

        *it = temp2;
        store_sse = _mm_set_ps1(0);
        temp2 = 0;
        k = 0;
        it++;
       

分段错误不是数组边界的问题,因为执行会使其下降到 _mm_store_ps 行。任何帮助将不胜感激,谢谢!

编辑:问题出在 _mm_load_ps,当我使用 _mm_loadu_ps 时它运行良好。我使用静态数组作为 _mm_load_ps 的参数,所以我不知道为什么会遇到问题。

【问题讨论】:

顺便说一句,_mm_setzero_ps()_mm_set_ps1(0) 的更好替代品 非常感谢,已更改。关于如何解决对齐问题的任何见解? 我建议你在gdb下运行程序,当它SIGFAULTs检查指针变量的值。 【参考方案1】:

SSE 要求其内存访问使用 16 字节对齐的地址。如果您不是从数组外部读取数据,这可能是您的问题。

尝试使用_mm_storeu_ps_mm_loadu_ps,它们是未对齐的版本。它们会运行得慢一点,但它们会起作用。确认是问题所在后,首先尝试对齐内存以获得最佳性能。

【讨论】:

我实际上尝试过 _mm_storeu_ps 并且我之前仍然遇到分段错误,但是现在我同时使用了 _mm_storeu_ps 和 _mm_loadu_ps,它可以工作。我想我已经为我在 _mm_store_ps 函数(临时数组和 store_sse)中使用的两个参数对齐了内存,所以我想知道对齐问题如何仍然发生?对于我在 _mm_load_ps 函数中使用的两个数组,我使用以下语法:'float arr[rs1 * rs2] __attribute__((__aligned__(16))), left_arr[ls1 * ls2] __attribute__((__aligned__(16)));'这不意味着它应该已经对齐了吗?如果相关,我正在使用 g++。 很容易检查。尝试在您的负载/存储周围做一个assert(((intptr_t)addr &amp; 15) == 0) 抱歉,我的说法有点过头了,你能解释一下这是什么意思吗? addr 是一个指针。 16字节对齐表示addr%16 == 0,所以addr的最低4位应该是0 数组已对齐,但您的索引导致加载未对齐。

以上是关于SSE _mm_store_ps 分段错误问题的主要内容,如果未能解决你的问题,请参考以下文章

Intel SSE Intrinsics _mm_load_si128 分段错误,

使用基本 SSE 指令的分段错误

使用结果浮点数时的 SSE SIMD 分段错误

SSE指令需要数据对齐

xmm 指令 - 内存源操作数的分段错误

使用 SSE 错误 __m128 到 *float 转换的矩阵乘法?