Tag: 微型优化

使用xor reg,reg优于mov reg,0吗?

在x86上有两种众所周知的方法来将整数寄存器设置为零值。 或 mov reg, 0 要么 xor reg, reg 有一种观点认为,第二个变体是更好的,因为值0没有存储在代码中,并节省了生成的机器代码的几个字节。 这绝对是好的 – 使用更less的指令caching,这有时可以允许更快的代码执行。 许多编译器产生这样的代码。 然而,异或指令和改变相同寄存器的先前指令之间存在正式的指令间依赖关系。 由于存在依赖性,后者的指令需要等到前一个指令完成,这可以减less处理器单元的负载并伤害性能。 add reg, 17 ;do something else with reg here xor reg, reg 很显然,无论初始寄存器值如何,异或的结果都是完全相同的。 但是处理器能够识别这个吗? 我在VC ++ 7中尝试了以下testing: const int Count = 10 * 1000 * 1000 * 1000; int _tmain(int argc, _TCHAR* argv[]) { int i; DWORD start = […]

将Sqrt(x)计算为x * InvSqrt(x)是否在Doom 3 BFG代码中有意义?

我浏览了最近发布的Doom 3 BFG源代码 ,当时我遇到了一些似乎没有任何意义的东西。 Doom 3将math函数包装在idMath类中。 一些函数只是从math.h获得相应的函数,但有些函数是重新实现(例如idMath :: exp16() ),我认为它们的性能要高于math.h (可能会牺牲精度)。 然而,让我感到困惑的是他们实现float idMath::Sqrt(float x)函数的方式: ID_INLINE float idMath::InvSqrt( float x ) { return ( x > FLT_SMALLEST_NON_DENORMAL ) ? sqrtf( 1.0f / x ) : INFINITY; } ID_INLINE float idMath::Sqrt( float x ) { return ( x >= 0.0f ) ? x * InvSqrt( x ) […]

DateTime.DayOfWeek微优化

首先: 我只是为了好玩而渴望学习这个问题。 我不得不承认我喜欢搞微观优化(虽然他们从来没有在我的任何开发中导致速度的显着提高)。 DateTime.DayOfWeek方法不代表我的任何应用程序的瓶颈。 而且在任何其他方面都不太可能成为问题。 如果有人认为这种方法对应用程序的性能有影响,他应该考虑什么时候进行优化 ,然后进行性能分析。 用ILSpy反编译DateTime类,我们找出DateTime.DayOfWeek是如何实现的: [__DynamicallyInvokable] public DayOfWeek DayOfWeek { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get { return (DayOfWeek)((this.InternalTicks / 864000000000L + 1L) % 7L); } } public long Ticks { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get { return this.InternalTicks; […]

在执行uop数量不是处理器宽度倍数的循环时性能是否降低?

我想知道在近期的x86处理器上,各种尺寸的循环如何作为uops数量的函数。 彼得·科尔德斯(Peter Cordes)的一句话引起了另外一个问题 : 我还发现,如果循环不是4个uops的倍数,那么循环缓冲区中的uop带宽不是每个周期4个常量。 (即它是abc,abc,…;不是abca,bcab,…)。 Agner Fog的微文档不幸的是在循环缓冲区的限制上并不清楚。 这个问题是关于循环是否需要N个uop的倍数来执行最大uop吞吐量,其中N是处理器的宽度。 (即4个用于最近的英特尔处理器)。 谈论“宽度”并计数微波时,有许多复杂的因素,但我最想忽略这些因素。 特别是,假设没有微观或macros观融合。 彼得给出了下面的例子,在它的内部有7个uops循环: 一个7-uop循环将发出4 | 3 | 4 | 3 |组…我还没有testing过较大的循环(不适合在循环缓冲区中),以查看下一个指令是否可能迭代在同一组中发出,但是我认为不是。 更一般地说,声明是每个迭代循环的x uops在它的体内至less需要ceil(x / 4)迭代,而不是简单的x / 4 。 这对一些或所有最近的x86兼容处理器是否正确?

INC指令与ADD 1:有关系吗?

大多数情况下,我现在远离INC和DEC,因为他们做了部分条件代码更新,这可能会导致pipe道中有趣的停顿,而ADD / SUB则不会。 所以在哪里不重要(大多数地方),我使用ADD / SUB来避免摊位。 我只在保持代码小的时候才使用INC / DEC,例如,在一个或两个指令的大小足够大的caching行中进行匹配。 这可能是毫无意义的纳米[字面上!] – 优化,但我在我的编码习惯相当老派。 作者:@Ira Baxter 上面的片段来自INC和DEC指令为什么不影响进位标志? 而且我想问一下,为什么会导致pipe道堵塞,而添加不了? 毕竟,add和inc都会更新标志寄存器。 唯一的区别是inc不更新CF. 但为什么这很重要?