我了解到一些Intel/AMD CPU可以使用SSE/AVX进行并行乘加操作:
Sandy Bridge和Haswell SSE2/AVX/AVX2每个周期的FLOPS。
我想知道如何在代码中最好地实现这个操作,并想了解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))
,还是乘法和加法所使用的寄存器必须是独立的?
最后,这如何应用于FMA(Haswell)?_mm_add_ps(sum, _mm_mul_ps(a1, b1))
是否会自动转换为单个FMA指令或微操作?
addps
的延迟为 3 个时钟周期。但吞吐量为 1。因此,您需要至少 3 条独立的求和链来充分利用它。您目前有 4 条,所以这是足够的。 - Mysticial-O3
下融合mul/add内置函数,即使在FLT_EVAL_METHOD=0而不是2的情况下也是如此。这得到了一些文档的支持(保持临时无限精度始终是合法的,以允许折叠表达式)。关于这个问题有一个新问题。 - Peter Cordes