micro-optimization相关内容
在C中,如果我有一个如下所示的函数调用 // main.c ... do_work_on_object(object, arg1, arg2); ... // object.c void do_work_on_object(struct object_t *object, int arg1, int arg2) { if(object == NULL) { return;
..
当我在https://godbolt.org上尝试不同的编译器时,我注意到编译器生成如下代码是非常常见的: push rax push rbx push rcx call rdx pop rcx pop rbx pop rax 我知道每个push或pop做两件事: 将操作数移入/移出堆栈空间 递增/递减堆栈指针(RSP) 因此
..
据我所知,在现代无序CPU上,最昂贵的东西之一是状态,因为该状态必须在多个版本中进行跟踪,并在许多指令等方面保持最新。 一些指令集,如x86和ARM,广泛使用标志,这是在成本模型不是今天的时候引入的,标志只需要几个逻辑门。类似于每条算术指令设置标志以检测零、进位和溢出。 更新现代无序实现的成本是否特别高?使得例如ADD指令更新进位标志,并且这必须被跟踪,因为尽管它可能永远不会被使用,但是有
..
英特尔recommends使用指令前缀缓解JCC错误的性能后果。 如果使用/QIntel-jcc-erratum编译MSVC,则遵循建议,并插入前缀指令,如下所示: 3E 3E 3E 3E 3E 3E 3E 3E 3E 48 8B C8 mov rcx,rax ; with redundant 3E prefixes They sayMSVC在前缀不可用时求助于NOPS。
..
我一直在想,在更好地利用CPU缓存(众所周知,它受益于引用的局部性)方面,哪种方法更有效--两个循环,每个循环迭代同一数学数字集,每个循环都有不同的Body语句(例如,对集合中的每个元素调用一个函数),或者让一个Body循环执行两个(或更多)Body语句。在所有循环之后,我们假定应用程序状态相同。 在我看来,拥有两个循环将引入较少的缓存未命中和驱逐,因为循环使用的更多指令和数据可以放入缓存中。我
..
在最近的x86体系结构上失败的存储到加载转发的成本是多少? 具体而言,由于加载部分与较早的存储重叠,或者较早的加载或存储跨越导致转发失败的某些对齐边界而失败的存储到加载转发。 当然会有延迟成本:它有多大?是否还有吞吐量成本,例如,失败的存储到加载转发是否使用其他加载和存储甚至其他非内存操作无法使用的额外资源? 当存储的所有部分都来自存储缓冲区时,与存储缓冲区和L1混合的情况有什么不同
..
enter和 有什么区别 推送ebpmov ebp, esp子 esp, 嗯 说明?有性能差异吗?如果是这样,哪个更快,为什么编译器总是使用后者? 与 leave 和 类似 mov esp, ebp流行音乐 说明. 解决方案 存在性能差异,尤其是enter.在现代处理器上,这解码到大约 10 到 20 µops,而三个指令序列大约是 4 到 6,具体取决于架构.有关详细信
..
这是我想出的一点微优化好奇心: 结构定时器{布尔运行{假};整数滴答声{0};无效 step_versionOne(int mStepSize) {如果(运行)滴答声 += mStepSize;}无效 step_versionTwo(int mStepSize) {滴答声 += mStepSize * static_cast(运行);}}; 这两种方法似乎实际上做同样的事情.第二个版
..
您是否注意到,如果您在任何 date() 之前在脚本中设置实际时区,date() 函数的运行速度比平常快 2 倍称呼?我对此非常好奇. 看看这段简单的代码: 它只是使用 for 循环调用 date() 函数 100,000 次.我得到的结果总是在 1.6 秒 左右(Windows,PHP 5.3.5)但是…… 如果我再次设置相同的时区,在开始前添加一条荒谬的线: date_de
..
编码是否有任何(非微优化)性能提升 f1 = 200f/2 对比 float f2 = 200f * 0.5 几年前我的一位教授告诉我,浮点除法比浮点乘法慢,但没有详细说明原因. 这种说法是否适用于现代 PC 架构? 更新1 关于评论,请同时考虑这种情况: float f1;浮动 f2 = 2浮动 f3 = 3;for( i =0 ; i
..
有两种众所周知的方法可以在 x86 上将整数寄存器设置为零值. 要么 mov reg, 0 或 xor reg, reg 有人认为第二种变体更好,因为值 0 没有存储在代码中,并且可以节省生成的机器代码的几个字节.这绝对是好的 - 使用更少的指令缓存,这有时可以允许更快的代码执行.许多编译器生成这样的代码. 但是,在 xor 指令和更改同一寄存器的任何较早指令之间,在形式上存在
..
总的来说,我认为我对延迟和吞吐量之间的区别有很好的理解.但是,对于英特尔 Intrinsics,我不清楚延迟对指令吞吐量的影响,尤其是在按顺序(或几乎按顺序)使用多个内部调用时. 例如,让我们考虑: _mm_cmpestrc 这在 Haswell 处理器上的延迟为 11,吞吐量为 7.如果我在循环中运行这条指令,我会在 11 个周期后获得一个连续的每个周期输出吗?由于这需要一次运行 11
..
我记得在我的架构类中假设 L1 缓存命中是 1 个周期(即与寄存器访问时间相同),但在现代 x86 处理器上实际上是这样吗? L1 缓存命中需要多少个周期?与注册访问权限相比如何? 解决方案 这里有一篇关于这个主题的精彩文章: http://arstechnica.com/gadgets/reviews/2002/07/caching.ars/1 回答您的问题 - 是的,
..
我一直在研究一些 Java 原始集合(trove、 如果没有final boolean[] used,函数会说“当索引小于当前对象的used字段的当前值的长度时,获取当前对象的 used 字段的当前值,并对索引 i 处的元素进行处理." JIT 可能更容易证明循环绑定不变量以消除过多的绑定检查等,因为它可以更轻松地确定什么会导致 used 的值发生变化.即使忽略多个线程,如果 p.appl
..
这是对之前线程中的一些评论的跟进: 递归斐波那契装配 以下代码片段计算斐波那契数,第一个示例带有循环,第二个示例带有计算跳转(索引分支)到展开的循环.这是在带有 Intel 3770K 3.5ghz 处理器的 Windows 7 Pro 64 位模式下使用 Visual Studio 2015 Desktop Express 进行测试的.通过 fib(0) 到 fib(93) 的单循环
..
可能的重复: 在Java中使用final关键字会提高性能吗? final 修饰符具有 不同的后果java取决于您将其应用于什么.我想知道的是,它是否另外可以帮助编译器创建更高效的字节码.我想这个问题深入到 JVM 的工作方式,并且可能是特定于 JVM 的. 那么,根据您的专业知识,以下任何一项对编译器有帮助,还是您只是出于正常的 Java 原因使用它们? 期末班 最终方法
..
从 Java 中的 String 中去除所有不可打印字符的最快方法是什么? 到目前为止,我已经尝试并测量了 138 字节、131 个字符的字符串: String 的 replaceAll() - 最慢的方法 517009 结果/秒 预编译一个 Pattern,然后使用 Matcher 的 replaceAll() 637836 个结果/秒 使用 StringBuff
..
我有一个特别的问题.我会尽量准确地描述这一点. 我正在做一个非常重要的“微优化".一次运行数天的循环.所以如果我能减少这个循环时间,它需要一半的时间.10 天会减少到只有 5 天等等. 我现在拥有的循环是函数:“testbenchmark1". 我有 4 个索引需要像这样循环增加.但是当从列表中访问索引时,实际上需要一些额外的时间,正如我所注意到的.这就是我想知道是否有其他解决方
..
以下哪种技术是将整数除以 2 的最佳选择,为什么? 技术一: x = x >>1; 技术二: x = x/2; 这里x是一个整数. 解决方案 使用最能描述您要执行的操作的操作. 如果您将数字视为位序列,请使用 bitshift. 如果您将其视为数值,请使用除法. 请注意,它们并不完全等效.对于负整数,它们可以给出不同的结果.例如: -5/2 = -2-5 >>
..
为了清楚起见,我不会在这里寻求任何形式的可移植性,因此任何将我绑定到某个盒子的解决方案都可以. 基本上,我有一个 if 语句,该语句在 99% 的时间评估为真,并且我试图勉强维持每一个性能时钟,我可以发出某种编译器命令吗(使用 GCC 4.1.2 和 x86ISA,如果重要的话)告诉分支预测器它应该为那个分支缓存? 解决方案 是的.http://kerneltrap.org/node
..