_mm_load_ps导致段故障

时间:2014-01-09 09:16:14

标签: c++ x86 sse simd memory-alignment

我有一个代码段。该片段只加载2个数组并使用SSE计算它们之间的点积。

代码在这里:

using namespace std;

long long size = 3200000;

float* _random()
{
    unsigned int seed = 123;
    //    float *t = malloc(size*sizeof(float));
    float *t = new float[size];
    int i;
    float num = 0.0;
    for(i=0; i < size; i++) {
        num = rand()/(RAND_MAX+1.0);
        t[i] = num;
    }
    return t;
}

float _dotProductVectorSSE(float *s1, float *s2)
{
    float prod;
    int i;
    __m128 X, Y, Z;

    for(i=0; i<size; i+=4)
    {
        X = _mm_load_ps(&s1[i]);
        Y = _mm_load_ps(&s2[i]);
        X = _mm_mul_ps(X, Y);
        Z = _mm_add_ps(X, Z);
    }

    float *v = new float[4];
    _mm_store_ps(v,Z);

    for(i=0; i<4; i++)
    {
//        prod += Z[i];
        std::cout << v[i] << endl;
    }

    return prod;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    time_t start, stop;
    double avg_time = 0;
    double cur_time;
    float* s1 = NULL;
    float* s2 = NULL;
    for(int i = 0; i < 100; i++)
    {
        s1 = _random();
        s2 = _random();
        start = clock();
        float sse_product = _dotProductVectorSSE(s1, s2);
        stop = clock();
        cur_time = ((double) stop-start) / CLOCKS_PER_SEC;
        avg_time += cur_time;
    }
    std::cout << "Averagely used " << avg_time/100 << " seconds." << endl;
    return a.exec();
}

当我跑步时,我得到了段故障。这是回溯:

(gdb) bt
0  0x0804965f in _mm_load_ps (__P=0xb6b56008) at /usr/lib/gcc/i586-suse-linux/4.6/include/xmmintrin.h:899
1  _dotProductVectorSSE (s1=0xb6b56008, s2=0xb5f20008) at ../simd/simd.cpp:37
2  0x0804987f in main (argc=1, argv=0xbfffee84) at ../simd/simd.cpp:80

Diassembler:

0x8049b30          push   %ebp
0x8049b31  <+0x0001>         push   %edi
0x8049b32  <+0x0002>         push   %esi
0x8049b33  <+0x0003>         push   %ebx
0x8049b34  <+0x0004>         sub    $0x2c,%esp
0x8049b37  <+0x0007>         mov    0x804c0a4,%esi
0x8049b3d  <+0x000d>         mov    0x40(%esp),%edx
0x8049b41  <+0x0011>         mov    0x44(%esp),%ecx
0x8049b45  <+0x0015>         mov    0x804c0a0,%ebx
0x8049b4b  <+0x001b>         cmp    $0x0,%esi
0x8049b4e  <+0x001e>         jl     0x8049b7a <_Z20_dotProductVectorSSEPfS_+74>
0x8049b50  <+0x0020>         jle    0x8049c10 <_Z20_dotProductVectorSSEPfS_+224>
0x8049b56  <+0x0026>         add    $0xffffffff,%ebx
0x8049b59  <+0x0029>         adc    $0xffffffff,%esi
0x8049b5c  <+0x002c>         xor    %eax,%eax
0x8049b5e  <+0x002e>         shrd   $0x2,%esi,%ebx
0x8049b62  <+0x0032>         add    $0x1,%ebx
0x8049b65  <+0x0035>         shl    $0x2,%ebx
**0x8049b68  <+0x0038>         movaps (%edx,%eax,4),%xmm0**
0x8049b6c  <+0x003c>         mulps  (%ecx,%eax,4),%xmm0
0x8049b70  <+0x0040>         add    $0x4,%eax
0x8049b73  <+0x0043>         cmp    %ebx,%eax
0x8049b75  <+0x0045>         addps  %xmm0,%xmm1
0x8049b78  <+0x0048>         jne    0x8049b68 <_Z20_dotProductVectorSSEPfS_+56>
0x8049b7a  <+0x004a>         movaps %xmm1,0x10(%esp)
0x8049b7f  <+0x004f>         xor    %ebx,%ebx

我正在使用QtCreator并在.pro文件中定义:

QMAKE_CXXFLAGS += -msse -msse2
DEFINES += __SSE__
DEFINES += __SSE2__
DEFINES += __MMX__

请告诉我如何解决这个问题!

2 个答案:

答案 0 :(得分:4)

您无法确保数据是16字节对齐的(malloc / new通常不够) - 您需要使用_mm_loadu_ps代替{{1}处理你可能未对齐的数据,或者最好使用合适的方法来分配对齐的内存(例如Linux上的posix_memalign)。

请注意,如果可能,您应该_mm_load_ps和16字节对齐的内存,否则请使用_mm_load_ps,但请注意,这可能会在某些(较旧的)CPU上显着降低性能。

答案 1 :(得分:0)

请尝试以下链接。 http://flyeater.wordpress.com/2010/11/29/memory-allocation-and-data-alignment-custom-mallocfree/

你基本上分配了比你需要的更多的内存,然后计算模16的地址并使用从该地址开始的内存来加载/存储数据。 注意指针算术。

这里的大部分代码是ideone.com/fXKQhR取自上面的链接,样本用法。