C++ 使用_mm_load_pd时函数崩溃

C++ 使用_mm_load_pd时函数崩溃,c++,segmentation-fault,sse,intrinsics,C++,Segmentation Fault,Sse,Intrinsics,我有以下功能: template <typename T> void SSE_vectormult(T * A, T * B, int size) { __m128d a; __m128d b; __m128d c; double A2[2], B2[2], C[2]; const double * A2ptr, * B2ptr; A2ptr = &A2[0]; B2ptr = &B2[0]; a =

我有以下功能:

template <typename T>
void SSE_vectormult(T * A, T * B, int size)
{

    __m128d a;
    __m128d b;
    __m128d c;
    double A2[2], B2[2], C[2];
    const double * A2ptr, * B2ptr;
    A2ptr = &A2[0];
    B2ptr = &B2[0];
    a = _mm_load_pd(A);
    for(int i = 0; i < size; i+=2)
    {
        std::cout << "In SSE_vectormult: i is: " << i << '\n';
        A2[0] = A[i];
        B2[0] = B[i];
        A2[1] = A[i+1];
        B2[1] = B[i+1];
        std::cout << "Values from A and B written to A2 and B2\n";
        a = _mm_load_pd(A2ptr);
        b = _mm_load_pd(B2ptr);
        std::cout << "Values converted to a and b\n";
        c = _mm_mul_pd(a,b);
        _mm_store_pd(C, c);
        A[i] = C[0];
        A[i+1] = C[1];
    };
//    const int mask = 0xf1;
//    __m128d res = _mm_dp_pd(a,b,mask);
//    r1 = _mm_mul_pd(a, b);
//    r2 = _mm_hadd_pd(r1, r1);
//    c = _mm_hadd_pd(r2, r2);
//    c = _mm_scale_pd(a, b);
//    _mm_store_pd(A, c);
}
模板
无效SSE_向量(T*A、T*B、整数大小)
{
__m128da;
__m128d-b;
__m128d-c;
双A2[2],B2[2],C[2];
常数双*A2ptr,*B2ptr;
A2ptr=&A2[0];
B2ptr=&B2[0];
a=毫米负载pd(a);
对于(int i=0;istd::cout您的数据不保证按照SSE加载要求对齐16字节。请使用
\u mm\u loadu\u pd

    a = _mm_loadu_pd(A);
    ...
    a = _mm_loadu_pd(A2ptr);
    b = _mm_loadu_pd(B2ptr);
或者尽可能确保数据正确对齐,例如静态或局部数据:

alignas(16) double A2[2], B2[2], C[2];    // C++11, or C11 with <stdalign.h>

您可以使用
#ifdef
定义在目标编译器上工作的
对齐(x)
宏。

您的数据不保证按照SSE加载的要求对齐16字节。或者使用
\u mm\u loadu\u pd

    a = _mm_loadu_pd(A);
    ...
    a = _mm_loadu_pd(A2ptr);
    b = _mm_loadu_pd(B2ptr);
或者尽可能确保数据正确对齐,例如静态或局部数据:

alignas(16) double A2[2], B2[2], C[2];    // C++11, or C11 with <stdalign.h>
您可以使用
#ifdef
来定义在目标编译器上工作的
对齐(x)
宏。

如果查看,您可以看到函数uu mm_load_pd定义为:

__m128d _mm_load_pd (double *p);
因此,在您的代码中,A的类型应为double,但A的类型为tipe T,这是一个模板参数。您应该确保使用权限模板参数调用SSE_vectormult函数,或者只是删除模板并使用double类型,

如果您看到函数u mm_load_pd被定义为:

__m128d _mm_load_pd (double *p);

因此,在您的代码中,A的类型应为double,但A的类型为tipe T,这是一个模板参数。您应该确保使用权限模板参数调用SSE_vectormult函数,或者只是删除模板并使用double类型,

让我试着回答为什么您的代码在Linux而不是Windows中工作。代码在64中编译-位模式使堆栈按16字节对齐。但是,在windows上以32位模式编译的代码仅按4字节对齐,在Linux上不保证按16字节对齐

在64位系统上,GCC默认为64位模式。然而,即使在64位系统上,MSVC也默认为32位模式。因此,我猜您没有在windows中以64位模式编译代码,并且
\u mm\u load\u pd
\u mm\u store\u pd
都需要16字节对齐的地址,因此代码崩溃

您至少有三种不同的解决方案可以让您的代码在Windows中工作

  • 以64位模式编译代码
  • 使用未对齐的负载和存储(例如
    \u mm\u storeu\u pd
  • 按照Paul R的建议自行调整数据

  • 最好的解决方案是第三种解决方案,因为您的代码将在32位系统和未对齐的加载/存储速度慢得多的旧系统上运行。

    让我试着回答为什么您的代码在Linux而不是Windows下运行。在64位模式下编译的代码堆栈对齐16字节。但是,在32位模式下编译的代码只有4字节te在windows上对齐,在Linux上不保证16字节对齐

    在64位系统上,GCC默认为64位模式。然而,即使在64位系统上,MSVC也默认为32位模式。因此,我猜您没有在windows中以64位模式编译代码,并且
    \u mm\u load\u pd
    \u mm\u store\u pd
    都需要16字节对齐的地址,因此代码崩溃

    您至少有三种不同的解决方案可以让您的代码在Windows中工作

  • 以64位模式编译代码
  • 使用未对齐的负载和存储(例如
    \u mm\u storeu\u pd
  • 按照Paul R的建议自行调整数据

  • 最好的解决方案是第三种解决方案,因为您的代码将在32位系统和未对齐的加载/存储速度慢得多的旧系统上工作。

    假设您运行的是64位windows,请将代码合并为64位。64位模式下的堆栈是16字节对齐的,但在32位窗口中只有4字节对齐。您需要16字节对齐用于您正在使用的加载和存储。假设您正在运行64位windows,请将代码合并为64位。64位模式下的堆栈是16字节对齐的,但在32位windows中只有4字节对齐。您正在使用的加载和存储需要16字节对齐。