cYr*_*rus 7 c gcc simd vectorization
我正在为一个项目使用GCC SIMD向量扩展,一切都很好但是转换,它们只是重置向量的所有组件.
在手动状态:
可以从一种向量类型转换为另一种向量类型,前提是它们具有相同的大小(实际上,您也可以将向量转换为相同大小的其他数据类型).
这是一个简单的例子:
#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] );
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我不是那个汇编大师,但我只看到一些字节移动:
[...] 400454: f2 0f 10 1d 1c 02 00 movsd 0x21c(%rip),%xmm3 40045b: 00 40045c: bf 49 06 40 00 mov $0x400649,%edi 400461: f2 0f 10 15 17 02 00 movsd 0x217(%rip),%xmm2 400468: 00 400469: b8 04 00 00 00 mov $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 add $0x8,%rsp 400482: e9 59 ff ff ff jmpq 4003e0
我怀疑向量等价于标量:
*( int * )&float_value = int_value;
Run Code Online (Sandbox Code Playgroud)
你怎么解释这种行为?
这就是矢量强制转换定义要做的事情(其他任何东西都会完全疯狂,并且会使标准的矢量编程习惯用起来非常痛苦).如果你想真正获得转换,你可能想要使用某种类型的内在函数,比如_mm_cvtepi32_ps(这会打破你的矢量代码的漂亮的架构独立性,当然,这也很烦人;一种常见的方法是使用一个定义便携式"内在函数"集的翻译标题.
为什么这有用?各种原因,但这里是最大的:
在矢量代码中,您几乎不想分支.相反,如果您需要有条件地执行某些操作,则评估条件的两侧,并使用蒙版来选择适当的结果.这些掩码矢量"自然地"具有整数类型,而您的数据矢量通常是浮点数; 你想要使用逻辑运算来组合这两者.如果矢量转换只是重新解释位,这种非常常见的习惯是最自然的.
当然,可以解决这个案例,或任何其他一些常见的矢量习语,但"矢量是一个包位"视图是非常常见的,并反映了大多数矢量程序员的想法.
| 归档时间: |
|
| 查看次数: |
2523 次 |
| 最近记录: |