【发布时间】:2012-09-04 16:55:19
【问题描述】:
我在一个项目中使用 GCC SIMD 向量扩展,一切都很好,但是强制转换,他们只是重置向量的所有组件。
manual 声明:
只要大小相同,就可以从一种向量类型转换为另一种向量类型(实际上,您也可以将向量转换为相同大小的其他数据类型或从其他数据类型转换)。
这是一个简单的例子:
#include <stdio.h>
typedef int int4 __attribute__ (( vector_size( sizeof( int ) * 4 ) ));
typedef float float4 __attribute__ (( vector_size( sizeof( float ) * 4 ) ));
int main()
{
int4 i = { 1 , 2 , 3 , 4 };
float4 f = { 0.1 , 0.2 , 0.3 , 0.4 };
printf( "%i %i %i %i\n" , i[0] , i[1] , i[2] , i[3] );
printf( "%f %f %f %f\n" , f[0] , f[1] , f[2] , f[3] );
f = ( float4 )i;
printf( "%f %f %f %f\n" , f[0] , f[1] , f[2] , f[3] );
}
使用gcc cast.c -O3 -o cast 编译并在我的机器上运行我得到:
1 2 3 4
0.100000 0.200000 0.300000 0.400000
0.000000 0.000000 0.000000 0.000000 <-- no no no
我不是那个汇编大师,但我只是在这里看到了一些字节移动:
[...] 400454: f2 0f 10 1d 1c 02 00 movsd 0x21c(%rip),%xmm3 40045b: 00 40045c: bf 49 06 40 00 移动 $0x400649,%edi 400461: f2 0f 10 15 17 02 00 movsd 0x217(%rip),%xmm2 400468: 00 400469: b8 04 00 00 00 移动 $0x4,%eax 40046e: f2 0f 10 0d 12 02 00 movsd 0x212(%rip),%xmm1 400475:00 400476: f2 0f 10 05 12 02 00 movsd 0x212(%rip),%xmm0 40047d:00 40047e: 48 83 c4 08 添加 $0x8,%rsp 400482:e9 59 ff ff ff jmpq 4003e0我怀疑标量的向量等价物:
*( int * )&float_value = int_value;
你如何解释这种行为?
【问题讨论】:
-
是的,看起来就是这样——按位转换。 (或者更确切地说,根本没有转换)所以你得到 4 个非规范化浮点数而不是实际值转换。
-
这就是向量转换的定义(其他任何事情都将是完全疯狂的,并且会使标准向量编程习语编写起来非常痛苦)。如果您想实际进行转换,您可能希望使用某种内在函数,例如
_mm_cvtepi32_ps(这会破坏矢量代码的良好架构独立性,当然,这也很烦人;一种常见的方法是使用定义一组可移植的“内在”的翻译头)。 -
我明白你的意思,但问题变成了:这个 cast 什么时候有用?
-
@cYrus 信不信由你,我实际上使用这个(按位)转换比值转换更频繁。
-
@StephenCanon 如果您想将该评论转化为答案,我很乐意接受。
标签: c gcc vectorization simd