【发布时间】:2017-06-03 14:36:47
【问题描述】:
有这个程序集摘录:
movl (%ecx,%edx,4), %eax
...
incl %eax
movl %eax, (%ecx,%edx,4)
翻译成 c :
a[i] += 1;
与:
a -> ecx and i -> edx
我的问题是使用 eax 作为中间人有什么意义?是更快还是不能直接增加内存值?
【问题讨论】:
-
您可能正在使用编译器(GCC?)生成未优化的代码。尝试使用
-O3进行编译 -
这样做很可能更快,“使用 eax 作为中间人”。将复杂的 CISC 样式指令(将分解为一系列加载和存储 µops)分解为多个更简单的 RISC 样式指令一直是 x86 处理器众所周知的优化技术。也就是说,可以直接增加内存:
incl (%ecx,%edx,4),您或编译器都可以生成该代码。所以这真的取决于你的编译器的代码生成策略和你可能设置的任何优化开关。 -
Here is an older article that delves into the relevance and merits of this optimization technique。并非他所说的一切都是 100% 正确的,而今天,您几乎可以忽略 INC 和 ADD 之间的区别,因为 Pentium 4 已经过时了。但是,您仍然可以看到,这里的选择是一个相当复杂且值得商榷的问题。不确定您的技能水平,很难为这个问题写一个好的答案。也许您可以详细说明您提出问题的动机?目前,我已经投票结束,因为“过于宽泛”。
-
在这两种情况下,对于 Skylake,延迟是相同的:5 个周期。但是,单指令方法需要 4 微秒,而三指令则需要 5 微秒(而且更长)。单条指令对端口 4 的压力较小(Skylake 中唯一进行存储的指令)。所有主流编译器seem to prefer the one instruction approach.
-
如果没有上下文(该程序集摘录是如何创建的),就不可能回答这个问题。它可能比直接递增值要慢,然后再次如果您追求性能,则很可能创建比将数组的单个元素递增 1 更好的代码,因此推理 3 条汇编指令的性能是毫无意义的。如果算法没有希望,或者数据结构不是最优的,那么 3 对 1 指令就是边际差异。
标签: assembly memory cpu-registers