Eik*_*ike 3 c++ sse simd multiplication in-place
我已经编写了一些矢量方法,这些方法可以进行简单的数学就地计算或复制,并且对于就地变体共享相同的惩罚.
最简单的可以归结为这样的东西:
void scale(float* dst, const float* src, int count, float factor)
{
__m128 factorV = _mm_set1_ps(factorV);
for(int i = 0; i < count; i+= 4)
{
__m128 in = _mm_load_ps(src);
in = _mm_mul_ps(in, factorV);
_mm_store_ps(dst, in);
dst += 4;
src += 4;
}
}
Run Code Online (Sandbox Code Playgroud)
测试代码:
for(int i = 0; i < 1000000; i++)
{
scale(alignedMemPtrDst, alignedMemPtrSrc, 256, randomFloatAbsRange1);
}
Run Code Online (Sandbox Code Playgroud)
在测试时,即在SAME缓冲区上重复操作此函数时,我发现如果dst和src相同,速度是相同的.如果它们不同,它的速度要快70倍.写作时主要循环(即_mm_store_ps)
有趣的是,相同的行为不适用于添加,即+ =很好地工作,只有*=是一个问题..
-
评论已经回答了这个问题.在人工测试期间它是非正规的.
你的factor产生了不正常的结果吗?非零但小于FLT_MIN?如果在此外面有一个循环,它会重复地在同一个块上循环,那么数字可能会变得足够小以至于需要缓慢的FP辅助.
(原来,这是OP的问题).
重复的原位乘法使得数字越来越小,因子低于1.0.复制和缩放到不同的缓冲区每次都使用相同的输入.
它不需要额外的时间来产生+-Inf或NaN产生结果,但它至少会在英特尔CPU上逐渐下溢到次正常.这是-ffast-math设置DAZ/FTZ 的一个原因- 下溢时刷新为零.
我想我已经读到AMD没有FP辅助微处理器处理低于正常值,但英特尔确实如此.
英特尔CPU上有一个性能计数器,fp_assist.any当子正常结果需要额外的微码uop来处理特殊情况时会计数.(我认为它与前端和OoO执行官一样具有侵入性.但它确实很慢.)
从硬件架构的角度来看,为什么非规范化浮点数比其他浮点数慢得多?
为什么icc会为简单的主要部件生成奇怪的装配?(显示ICC如何在开始时设置FTZ/DAZ main,具有默认的快速数学设置.)