如何使用SSE/AVX

问题描述 投票:0回答:2
.

。 我喜欢知道如何在代码中做到这一点,我也想知道它在CPU中的内部完成。 我的意思是使用超级阶段的体系结构。 假设我想做一笔长的款项,例如SSE中的以下内容:
//sum = a1*b1 + a2*b2 + a3*b3 +... where a is a scalar and b is a SIMD vector (e.g. from matrix multiplication) sum = _mm_set1_ps(0.0f); a1 = _mm_set1_ps(a[0]); b1 = _mm_load_ps(&b[0]); sum = _mm_add_ps(sum, _mm_mul_ps(a1, b1)); a2 = _mm_set1_ps(a[1]); b2 = _mm_load_ps(&b[4]); sum = _mm_add_ps(sum, _mm_mul_ps(a2, b2)); a3 = _mm_set1_ps(a[2]); b3 = _mm_load_ps(&b[8]); sum = _mm_add_ps(sum, _mm_mul_ps(a3, b3)); ... 我的问题是如何将其转换为同时乘积并添加? 数据可以取决于吗? 我的意思是CPU可以同时进行

_mm_add_ps(sum, _mm_mul_ps(a1, b1))

或在乘法中使用的寄存器,并且添加必须是独立的? lastly这如何适用于FMA(与Haswell)?

_mm_add_ps(sum, _mm_mul_ps(a1, b1))
自动转换为单个FMA指令或微操作吗?
    

允许编译器融合分离的添加和乘积,即使这会改变最终结果(通过使其更准确)。

ANFMA只有一个圆形(它有效地保持了内部临时乘结果的无限精度),而添加 + mul具有两个。

当生效时,IEEE和C标准允许这样做,并且允许compilers默认情况下将其具有

#pragma STDC FP_CONTRACT ON

(但不是全部)。  GCC默认情况下将FMA收缩为FMA(默认的
ON

,但没有,例如
c sse cpu-architecture avx fma
2个回答
51
投票
)。

对于clang

,它仅由

-std=c*

启用。 (只有启用

-std=c++14

启用,仅在单个表达式中,例如
-ffp-contract=fast,而不是跨单独的c ++语句。)。
这与严格的浮点(或以GCC术语为
#pragma
vs.
a+b*c
)不同,这将允许其他类型的优化
可能会根据输入值增加舍入误差。  这是特殊的,因为FMA内部临时性的无限精度。如果在内部临时性中根本有任何舍入,则在严格的FP中不允许使用。

即使您启用了轻松的浮点,编译器可能仍然选择不融合,因为它可能希望您知道您已经在使用Interins。
so
最好的方法确保您实际上获得所需的FMA指令是您实际上使用提供的固有信息:
FMA3内在:
(AVX2 -Intel Haswell)

-ffast-math

,_
-fno-fast-math

_mm_fmadd_pd()

mm256_fmadd_pd()


大约有其他变化...

FMA4内在:(XOP- AMD推土机)

  • _mm_fmadd_ps()
    _mm256_fmadd_ps()
    
    
  • _mm_macc_pd()
    _mm256_macc_pd()
    
    
  • 大约有其他变化...

I在GCC 5.3,Clang 3.7,ICC 13.0.1和MSVC 2015中测试了以下代码(编译器版本19.00)。 _mm_macc_ps()

    正确的编译器选项(请参见下文)每个编译器将从
  • _mm256_macc_ps()
    生成
    float mul_add(float a, float b, float c) { return a*b + c; } __m256 mul_addv(__m256 a, __m256 b, __m256 c) { return _mm256_add_ps(_mm256_mul_ps(a, b), c); }
    指令(例如
    vfmadd
  • )。但是,只有MSVC未能与单个指令(例如
  • vfmadd213ss
    )合同。
    
    
    以下编译器选项足以生成
    mul_add
    指令(使用MSVC除外)。
  • mul_addv
  • GCC4.9不会与单个FMA指令合同,但由于至少GCC 5.1。我不知道其他编译器何时开始这样做。

21
投票
不像FMA运行的精度更高。我用MSVC ++ 2022在我的Zen4-CPU上测试了这一点:

vfmadd
结果为零,即通过两个手动操作可以有点取消操作。
当我第一次测试此代码时,我认为编译器本身用FMA操作替换了手动操作。我在拆卸中检查了一下,没有做任何替代。
    


最新问题
© www.soinside.com 2019 - 2025. All rights reserved.