C SSE矢量化中的错误结果

C SSE矢量化中的错误结果,c,x86,vectorization,sse,simd,C,X86,Vectorization,Sse,Simd,下面的代码生成以下输出: 六, 6. 0 140021597270387 这意味着只有前两个位置计算正确。但是,我处理的是long(4个字节),而且我可以容纳4个以上的long long* AA = (long*)malloc(32*sizeof(long)); long* BB = (long*)malloc(32*sizeof(long)); for(i = 0; i<4;i++){ AA[i] = 2; BB[i] = 3; } __m128i* m1 = (__

下面的代码生成以下输出:

六, 6. 0 140021597270387

这意味着只有前两个位置计算正确。但是,我处理的是long(4个字节),而且我可以容纳4个以上的long

long* AA = (long*)malloc(32*sizeof(long));
long* BB = (long*)malloc(32*sizeof(long));

for(i = 0; i<4;i++){
    AA[i] = 2;
    BB[i] = 3;
}

__m128i* m1 = (__m128i*) AA;
__m128i* m2 = (__m128i*) BB;

__m128i m3 = _mm_mul_epu32(m1[0],m2[0]);

long* CC = (long*) malloc(16 * sizeof(long));
CC = (long*)&m3;

for (i = 0; i < 4; i++)
    printf("%ld \n",CC[i]);
(和剩余向量)生成seg。过错有人能评论一下吗

感谢您不要使用大小不确定的类型,如
long
,请使用特定的fixed with类型,如
uint32\u t

2) 不要使用
malloc
-不能保证返回16字节对齐的内存,请使用或等效*

3) 不要在C中强制转换
malloc
(或任何其他函数返回
void*
)的结果

4) 不需要再分配一个缓冲区来打印结果

固定代码:

uint32_t* AA = memalign(32*sizeof(uint32_t), 16);
uint32_t* BB = memalign(32*sizeof(uint32_t), 16);

for (i = 0; i < 4; i++){
    AA[i] = 2;
    BB[i] = 3;
}

__m128i* m1 = (__m128i*)AA;
__m128i* m2 = (__m128i*)BB;

__m128i m3 = _mm_mul_epu32(m1[0], m2[0]);    // 2 x 32x32->64 bit unsigned multiplies -> m3

uint64_t* CC = (uint64_t*)&m3;

for (i = 0; i < 2; i++)                      // display 2 x 64 bit result values
    printf("%llu\n", CC[i]);
uint32_t*AA=memalign(32*sizeof(uint32_t),16);
uint32_t*BB=memalign(32*sizeof(uint32_t),16);
对于(i=0;i<4;i++){
AA[i]=2;
BB[i]=3;
}
__m128i*m1=(uu m128i*)AA;
__m128i*m2=(uu m128i*)BB;
__m128i m3=_mm_mul_epu32(m1[0],m2[0]);//2 x 32x32->64位无符号乘法->m3
uint64_t*CC=(uint64_t*)和m3;
对于(i=0;i<2;i++)//显示2 x 64位结果值
printf(“%llu\n”,CC[i]);

*请注意,根据您的平台,您可能需要使用除
memalign
之外的调用来分配适当对齐的内存,例如
posix\u memalign
\u mm\u malloc
\u aligned\u malloc
(WIN32).

为什么要分配
CC
,然后立即将
m3
的地址分配给它?
\uuuu m128i
可能有四个长字符,也可能没有。
long
的大小是特定于实现的,可以是32位或更大。在许多64位体系结构上,
long
实际上是64位的,因此
\uuuum128i
可能只能容纳两个long。您应该检查
sizeof(uu m128i)==4*sizeof(long)
。相关:在Windows上,long是32位的,但大多数64位类Unix系统都有64位long。你们说得对。在我的例子中,sizeof(long)是8…值得注意的是,
posix_memalign
不是跨平台的(没有窗口)。它也不是这样叫的:@PaulR:
\u mm\u mul\u epu32
被记录为只有两个乘法a0*b0和a2*b2。单个调用是否会将4
int32
s相乘?@legends2k:事实上,
\u mm\u mul\u epi32
/
\u mm\u mul\u epu32
执行2 x 32x32->64位整数相乘。如果您想要4 x 32x32->32位乘法器,那么您可以使用几个16位乘法器将其组合在一起,或者使用2 x
\u mm\u mul\u epu32
和一些移位/洗牌,或者如果精度不重要,则转换为浮点,使用
\u mm\u mul\u ps
,并将其转换回int。没有一条指令用于此。@PaulR:在上面的示例中,您将四个
int32\t
s打包到寄存器中,并调用
\u mm\u mul\u epu32
一次,其结果是两个
int64\t
,而您将每一个作为
int32
访问四次以打印输出。你不应该打两次电话给
\u mm\u mul\u epu32
吗?是的,对不起-我只是在解决OPs代码中的基本问题(即崩溃),而不太担心更精细的细节。我也会把展示部分整理一下。
uint32_t* AA = memalign(32*sizeof(uint32_t), 16);
uint32_t* BB = memalign(32*sizeof(uint32_t), 16);

for (i = 0; i < 4; i++){
    AA[i] = 2;
    BB[i] = 3;
}

__m128i* m1 = (__m128i*)AA;
__m128i* m2 = (__m128i*)BB;

__m128i m3 = _mm_mul_epu32(m1[0], m2[0]);    // 2 x 32x32->64 bit unsigned multiplies -> m3

uint64_t* CC = (uint64_t*)&m3;

for (i = 0; i < 2; i++)                      // display 2 x 64 bit result values
    printf("%llu\n", CC[i]);