C SSE矢量化中的错误结果
下面的代码生成以下输出: 六, 6. 0 140021597270387 这意味着只有前两个位置计算正确。但是,我处理的是long(4个字节),而且我可以容纳4个以上的longC 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 = (__
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。单个调用是否会将4int32
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]);