如果它们是16字节对齐,是否可以直接将浮点数转换为__m128?

dte*_*ech 14 c c++ sse alignment intrinsics

__m128如果它们是16字节对齐,是否安全/可能/建议直接转换浮点数?

我注意到使用_mm_load_ps_mm_store_ps"包装"原始数组会增加显着的开销.

我应该注意哪些潜在的陷阱?

编辑:

使用加载和存储指令实际上没有开销,我得到了一些数字混合,这就是为什么我有更好的性能.即使你能够在一个__m128实例中使用原始内存地址进行一些HORRENDOUS修改,当我运行测试时,如果没有_mm_load_ps指令则需要TWICE AS LONG完成,可能会回到一些故障安全代码路径.

Pau*_*l R 11

是什么让你想到这一点_mm_load_ps_mm_store_ps"增加了巨大的开销"?这是向/从SSE寄存器加载/存储浮点数据的常规方法,假设源/目标是内存(并且任何其他方法最终归结为此).

  • 保罗 - 你似乎是正确的,较低的时间实际上是由于我疏忽造成的一些数字不匹配.如果没有加载和存储功能,操作实际上需要更长时间,但仍然准确完成,可能会回落到某些故障安全状态. (7认同)
  • 我想你可能会错误地解释你的分析结果.听起来你正在比较显式加载/存储与编译器生成的加载/存储,但是相同的指令最有可能被"引擎盖下"使用 - 你只是看到了不同指令调度/循环展开/等的影响.看看你的代码,看看你正在测量什么是很有用的. (3认同)

Fra*_*kH. 8

有几种方法可以将float值放入SSE寄存器中; 可以使用以下内在函数:

__m128 sseval;
float a, b, c, d;

sseval = _mm_set_ps(a, b, c, d);  // make vector from [ a, b, c, d ]
sseval = _mm_setr_ps(a, b, c, d); // make vector from [ d, c, b, a ]
sseval = _mm_load_ps(&a);         // ill-specified here - "a" not float[] ...
                                  // same as _mm_set_ps(a[0], a[1], a[2], a[3])
                                  // if you have an actual array

sseval = _mm_set1_ps(a);          // make vector from [ a, a, a, a ]
sseval = _mm_load1_ps(&a);        // load from &a, replicate - same as previous

sseval = _mm_set_ss(a);           // make vector from [ a, 0, 0, 0 ]
sseval = _mm_load_ss(&a);         // load from &a, zero others - same as prev
Run Code Online (Sandbox Code Playgroud)

编译器会经常创建相同的指令不管你陈述_mm_set_ss(val)或者_mm_load_ss(&val)-尝试和拆卸你的代码.

在某些情况下,它可能有利于编写_mm_set_ss(*valptr)而不是_mm_load_ss(valptr)...取决于代码的(结构).

  • 我相信内在函数种类繁多的最大原因是:a)程序员可以选择直接使用常量而不是变量(比如,`__m128 s = _mm_set1_ps(M_PI);`而不是`float pi [4] = { M_PI,M_PI,M_PI,M_PI}; __ m128 s = _mm_load_ps(pi);`),和b)允许编译器优化某些情况,其中可以重用已经可用/先前加载的数据而不是发出另一个存储器访问.我倾向于编写代码"compact"并反汇编结果,以便了解它是否正确... (3认同)

JAB*_*JAB 5

请访问http://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx,这可能但不安全或不推荐.

您不应直接访问__m128字段.


这就是为什么:

http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/766c8ddc-2e83-46f0-b5a1-31acbb6ac2c5/

  1. 将float*转换为__m128将不起作用.C++编译器将赋值转换为__m128类型转换为SSE指令,将4个浮点数加载到SSE寄存器.假设编译了这个转换,它不会创建工作代码,因为不会生成SEE加载指令.

__m128变量实际上不是变量或数组.这是SSE寄存器的占位符,由C++编译器替换为SSE汇编指令.要更好地理解这一点,请阅读英特尔组装编程参考


St0*_*0fF 5

自从提出这个问题以来,已经过去了几年。要回答我的经验表明的问题:

是的

reinterpret_cast-将 afloat*转换为 a__m128*反之亦然是好的,只要它float*是 16 字节对齐的 - 示例(在 MSVC 2012 中):

__declspec( align( 16 ) ) float f[4];
return _mm_mul_ps( _mm_set_ps1( 1.f ), *reinterpret_cast<__m128*>( f ) );
Run Code Online (Sandbox Code Playgroud)