汇编程序任务:翻译

时间:2018-05-14 08:12:13

标签: assembly

Here given fragments of the source code and their translation

为什么.L21(比.L27长)比.L27快?

为什么flag -funroll-loops会加速loop1但不会加速loop2?

1 个答案:

答案 0 :(得分:1)

无论如何,关于你的问题......第一个循环在循环中没有依赖,即循环的每个迭代是独立的并且可以尽快计算(实际上除了最后一次迭代之外的所有循环都可以被丢弃,因为它们根本不影响返回值。

每次迭代的第二个循环取决于之前的结果,因此CPU必须等待每个下一个imul,直到前一个结果准备就绪。现代x86上的imul仍然具有大约1.0的吞吐量,但是延迟可能高于1.0并且不确定依赖性将做什么,完全取决于您未指定的目标CPU平台。 (像Peter Cordes这样的人可以肯定地回答这个特定的现代英特尔微架构,或者你可以自己阅读Agner的表格,但是由于你没有指定目标架构,我不认为有必要为我制作任何特定的现实世界的例子这个一般的聊天级别就足够了)

例如在80386上,我猜第二个循环会更快,因为它的指令较少,80386内部仍然非常“简单”,imul在任何一种情况下都需要几个时钟。在最新的英特尔CPU上,依赖性可能只是因此偏向于第一个,但并不多,因为imul今天相当快。

无论如何,这是一个很好的例子,如何首先整理你的算法,并调整它,将给你最大的性能增益,因为第一个循环不是一个真正的循环,并将其编写为简单的公式将使代码更快

奇怪的是,我在godbolt资源管理器中尝试过,现代编译器对此做了什么,而gcc做了一些非常复杂的事情来读取每个数组成员,或者指令墙究竟做了什么(懒得检查调试器)虽然clang编译器确实看到它并生成简化的公式:https://godbolt.org/g/p2MGHs

P.S。第一个循环可以简化为:

int loop1_fix(int *a, int x, int n) {
    if (0 < n) return a[n-1]*x*x*x*x;
    else return x*x*x;
}