当我尝试优化我的代码时,很长一段时间我一直在使用经验法则,加法和减法值1,乘法和除法值3,平方值3(我很少使用更一般的pow
函数,所以我没有经验法则),平方根值10。(我假设平方数只是乘法,所以值得3。)
这是2D轨道模拟的一个例子。要从重力计算和应用加速度,首先我得到从船到地球中心的距离,然后计算加速度。
D = sqrt( sqr(Ship.x - Earth.x) + sqr(Ship.y - Earth.y) ); // this is worth 19
A = G*Earth.mass/sqr(D); // this is worth 9, total is 28
但是,请注意,在计算D时,您采用平方根,但在下一次计算中使用它时,您将其平方。因此,你可以这样做:
A = G*Earth.mass/( sqr(Ship.x - Earth.x) + sqr(Ship.y - Earth.y) ); // this is worth 15
因此,如果我的经验法则属实,我几乎减少了一半的周期时间。
然而,我甚至不记得以前在哪里听过这条规则。我想问一下这些基本算术运算的实际周期时间是什么?
假设:
编辑:我想我真正想做的是查看ALU内部,并且只计算6个操作的逻辑循环时间。如果其中仍存在差异,请说明原因和原因。
注意:我没有看到机器代码的任何标签,所以我选择了下一个最接近的东西,汇编。为了清楚起见,我在谈论 x64架构中的实际机器代码操作。因此,我写的那些代码行是用C#,C,Javascript还是无关紧要。我敢肯定每种高级语言都会有不同的时间,所以我不想讨论这个问题。我觉得很遗憾没有机器代码标签,因为在谈论性能和/或操作时,你真的需要深入了解它。
答案 0 :(得分:10)
至少,必须了解操作至少有两个有趣的时间:延迟和吞吐量。
延迟是指从输入到输出的任何特定操作所需的时间。如果您有一系列操作,其中一个操作的输出被输入到下一个操作的输入中,则延迟将决定总时间。例如,最近的x86硬件上的整数乘法具有3个周期的延迟:完成单个乘法运算需要3个周期。整数加法的延迟为1个周期:结果在加法执行后的周期可用。延迟通常是正整数。
吞吐量是每单位时间可执行的独立操作的数量。由于CPU是流水线和超标量的,因此这通常不仅仅是延迟的倒数。例如,在最近的x86芯片上,即使延迟为1个周期,每个周期也可以执行4个整数加法运算。类似地,1个整数乘法可以平均每个周期执行,即使任何特定的乘法需要3个周期才能完成(这意味着你必须一次进行多次独立的乘法才能实现这一点)。
在讨论指令性能时,通常将吞吐量数量设为"反向吞吐量",这只是1 / throughput
。这使得直接与延迟数字进行比较变得容易,而无需在脑海中进行划分。例如,加法的逆吞吐量为0.25个周期,而延迟为1个周期,因此如果您有足够的独立添加,您可以立即看到它们,它们每个只使用0.25个周期。
下面我将使用反向吞吐量。
大多数简单指令都有固定的时序,至少在其reg-reg形式中。然而,一些更复杂的数学运算可能具有与输入相关的时序。例如,加法,减法和乘法通常在其整数和浮点形式中具有固定的时序,但在许多平台上,除法具有整数,浮点或两者的变量时序。 Agner的数字通常显示一个范围来表示这一点,但你不应该假设操作数空间已被广泛测试,特别是对于浮点数。
例如,下面的Skylake数字显示的范围较小,但如果由于操作数依赖性(可能更大)或其他因素而无法清除。
传递非正规输入或者自身非正规的结果可能会导致显着的额外成本,具体取决于非正规模式。您在指南中看到的数字通常假定没有非正规数,但您可能能够找到其他地方每次操作的非正常成本的讨论。
以上必要但通常没有足够的信息来完全符合性能要求,因为您还需要考虑其他因素,例如执行端口争用,前端瓶颈和等等。它已经足够开始,你只需要经验法则"数字如果我理解正确的话。
测量的延迟和逆吞吐量数字的推荐来源是Agner的迷雾guides。您想要 4下的文件。指令表:英特尔,AMD和VIA CPU的指令延迟,吞吐量和微操作故障列表,列出了各种AMD和Intel CPU的相当详尽的时序。您也可以直接从英特尔指南中获取某些CPU的数字,但我发现它们不如Agner那么完整且难以使用。
下面我将提取几个现代CPU的数字,以了解您感兴趣的基本操作。
Lat Inv Tpt
add/sub (addsd, subsd) 4 0.5
multiply (mulsd) 4 0.5
divide (divsd) 13-14 4
sqrt (sqrtpd) 15-16 4-6
所以"经验法则"延迟将是add / sub / mul all cost 1,division和sqrt分别约为3和4。对于吞吐量,规则分别为1,8,8-12。另请注意,延迟远远大于反向吞吐量,尤其是对于add,sub和mul:如果要达到最大吞吐量,则需要8个并行操作链。
Lat Inv Tpt
add/sub (addsd, subsd) 3 0.5
multiply (mulsd) 4 0.5
divide (divsd) 8-13 4-5
sqrt (sqrtpd) 14-15 4-8
Ryzen数字与最近的英特尔大致相似。加法和减法的潜伏期略低,乘法是相同的。延迟方面,经验法则仍然可以概括为add,sub,mul / div / sqrt的1/3/4,但精度有所下降。
这里,除法的延迟范围相当大,所以我希望它与数据有关。