C++ _mm_负载_ps导致的段故障
我有一个代码片段。该代码段仅加载2个数组,并使用SSE计算它们之间的点积 代码如下:C++ _mm_负载_ps导致的段故障,c++,x86,sse,simd,memory-alignment,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.
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();
}
散开器:
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
请告诉我如何解决这个问题 您不能确保数据是16字节对齐的(
malloc
/new
通常是不够的)-您需要使用\u mm\u loadu\u ps
而不是\u mm\u loadu\u ps
来处理可能不对齐的数据,或者最好使用合适的方法来分配对齐的内存(例如在Linux上)
请注意,如果可能的话,您应该使用
\u mm\u loadu\u ps
和16字节对齐的内存,否则使用\u mm\u loadu\u ps
,但请注意,这可能会显著降低某些(旧)CPU上的性能。您不能确保数据是16字节对齐的(malloc
/new
一般来说是不够的)-您可能需要使用\u mm\u loadu\u ps
而不是\u mm\u loadu\u ps
来处理可能未对齐的数据,或者最好使用合适的方法来分配对齐的内存(例如在Linux上)
请注意,如果可能,您应该使用\u mm\u loadu\u ps
和16字节对齐内存,否则使用\u mm\u loadu\u ps
,但请注意,这可能会显著降低某些(较旧)CPU的性能。请尝试下面的链接。
基本上,您分配的内存比您需要的多一点,然后计算模16的地址,并使用从该地址开始的内存来加载/存储数据。
注意指针运算
此处的大部分代码ideone.com/fXKQhR取自上面的链接“示例用法”。请尝试下面的链接。
基本上,您分配的内存比您需要的多一点,然后计算模16的地址,并使用从该地址开始的内存来加载/存储数据。
注意指针运算
这里的大部分代码ideone.com/fXKQhR来自上面的链接,示例用法。嗨,Paul,我对intrinsics编程还不熟悉。我看了一下_mm_loadu_ps,知道地址不需要16字节对齐。但是请告诉我,如何确保数据16字节对齐?嗨,Paul,我是intrinsics编程新手。我看了一下_mm_loadu_ps,知道地址不需要16字节对齐。但请告诉我,如何确保数据16字节对齐?
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
QMAKE_CXXFLAGS += -msse -msse2
DEFINES += __SSE__
DEFINES += __SSE2__
DEFINES += __MMX__