DrZ*_*214 3 optimization performance assembly x86-64 cycle
当我尝试优化我的代码时,很长一段时间我一直在使用经验法则,加法和减法值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
Run Code Online (Sandbox Code Playgroud)
但是,请注意,在计算D时,您采用平方根,但在下一次计算中使用它时,您将其平方.因此你可以这样做:
A = G*Earth.mass/( sqr(Ship.x - Earth.x) + sqr(Ship.y - Earth.y) ); // this is worth 15
Run Code Online (Sandbox Code Playgroud)
因此,如果我的经验法则属实,我几乎减少了一半的周期时间.
但是,我甚至不记得以前在哪里听过这条规则.我想问一下这些基本算术运算的实际循环时间是多少?
假设:
编辑:我想我真正要做的是查看ALU内部并仅计算6个操作的逻辑循环时间.如果其中仍存在差异,请说明原因和原因.
注意:我没有看到任何机器代码的标签,所以我选择了下一个最接近的东西,汇编.为了清楚起见,我在谈论x64架构中的实际机器代码操作.因此,我写的那些代码行是用C#,C,Javascript还是无关紧要.我敢肯定每种高级语言都会有不同的时间,所以我不想讨论这个问题.我认为没有机器代码标签是一种遗憾,因为在谈论性能和/或操作时,你真的需要深入了解它.
Bee*_*ope 10
至少,必须理解操作至少有两个有趣的时间:延迟和吞吐量.
延迟是指从输入到输出的任何特定操作所需的时间.如果您有一系列操作,其中一个操作的输出被输入到下一个操作的输入中,则延迟将决定总时间.例如,最近的x86硬件上的整数乘法具有3个周期的延迟:完成单个乘法运算需要3个周期.整数加法的延迟为1个周期:结果在加法执行后的周期可用.延迟通常是正整数.
吞吐量是每单位时间可以执行的独立操作的数量.由于CPU是流水线和超标量的,因此这通常不仅仅是延迟的倒数.例如,在最近的x86芯片上,即使延迟为1个周期,每个周期也可以执行4个整数加法运算.类似地,1个整数乘法可以平均每个周期执行一次,即使任何特定的乘法需要3个周期来完成(这意味着你必须立即进行多次独立的乘法才能实现这一点).
在讨论指令性能时,通常将吞吐量数量设为"反向吞吐量",这很简单1 / throughput.这使得直接与延迟数字进行比较变得容易,而无需在脑海中进行划分.例如,加法的逆吞吐量为0.25个周期,而延迟为1个周期,因此如果您有足够的独立添加,您可以立即看到它们,它们每个只使用0.25个周期.
下面我将使用反向吞吐量.
大多数简单的指令都有固定的时间,至少在它们的注册形式中.然而,一些更复杂的数学运算可能具有与输入相关的时序.例如,加法,减法和乘法通常在其整数和浮点形式中具有固定的时序,但在许多平台上,除法具有整数,浮点或两者的变量时序.Agner的数字通常会显示一个范围来表明这一点,但你不应该假设操作数空间已被广泛测试,特别是对于浮点数.
例如,下面的Skylake数字显示一个小范围,但不清楚这是由于操作数依赖性(可能更大)或其他原因.
传递非正规输入或自身非正规的结果可能会导致显着的额外成本,这取决于非正规模式.您将在指南中看到的数字通常假定没有非正规数,但您可能能够找到其他地方每次操作的非正常成本的讨论.
以上是必要但通常不足以完全限定性能的信息,因为您还有其他因素需要考虑,例如执行端口争用,前端瓶颈等.这足以开始,如果我理解正确,你只需要"经验法则"数字.
我推荐的测量延迟和反向吞吐量数据源是Agner的Fogs 指南.您需要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
Run Code Online (Sandbox Code Playgroud)
所以延迟的"经验法则"是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
Run Code Online (Sandbox Code Playgroud)
Ryzen数字与最近的英特尔大致相似.加法和减法的潜伏期略低,乘法是相同的.延迟方面,经验法则仍然可以概括为add,sub,mul/div/sqrt的1/3/4,但精度有所下降.
这里,除法的延迟范围相当大,所以我预计它与数据有关.