首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么‘`mov %eax,%eax;is’比‘nop`’快?

为什么‘`mov %eax,%eax;is’比‘nop`’快?
EN

Stack Overflow用户
提问于 2018-10-25 15:14:11
回答 1查看 550关注 0票数 5

显然,现代处理器可以判断您是否做了一些愚蠢的事情,比如将寄存器移动到自身(mov %eax, %eax),并对其进行优化。为了验证这一说法,我运行了以下程序:

代码语言:javascript
复制
#include <stdio.h>
#include <time.h>

static inline void f1() {
   for (int i = 0; i < 100000000; i++)
      __asm__(
            "mov %eax, %eax;"
            "nop;"
            );
}

static inline void f2() {
   for (int i = 0; i < 100000000; i++)
      __asm__(
            "nop;"
            );
}

static inline void f3() {
   for (int i = 0; i < 100000000; i++)
      __asm__(
            "mov %ebx, %eax;"
            "nop;"
            );
}

int main() {
   int NRUNS = 10;
   clock_t t, t1, t2, t3;

   t1 = t2 = t3 = 0;
   for (int run = 0; run < NRUNS; run++) {
      t = clock(); f1(); t1 += clock()-t;
      t = clock(); f2(); t2 += clock()-t;
      t = clock(); f3(); t3 += clock()-t;
   }

   printf("f1() took %f cycles on avg\n", (float) t1/ (float) NRUNS);
   printf("f2() took %f cycles on avg\n", (float) t2/ (float) NRUNS);
   printf("f3() took %f cycles on avg\n", (float) t3/ (float) NRUNS);

   return 0;
}

这给了我:

代码语言:javascript
复制
f1() took 175587.093750 cycles on avg
f2() took 188313.906250 cycles on avg
f3() took 194654.296875 cycles on avg

正如人们所预料的那样,f3()的发布速度最慢。但令人惊讶的是(至少对我来说),f1()f2()快。为什么会这样呢?

Update:使用-falign-loops进行编译在质量上具有相同的结果:

代码语言:javascript
复制
f1() took 164271.000000 cycles on avg
f2() took 173783.296875 cycles on avg
f3() took 177765.203125 cycles on avg
EN

回答 1

Stack Overflow用户

发布于 2018-10-26 11:41:48

链接文章中让我认为可以优化的部分是:“移动函数负责检查等效位置”。

这是关于SBCL中的(move r x)函数,而不是x86 mov指令。它讨论的是从低级中间语言生成代码时的优化,而不是通过硬件在运行时进行的优化。

mov %eax, %eaxnop都不是完全免费的。它们都耗费了前端的吞吐量,而且mov %eax,%eax甚至不是64位模式下的NOP (它零-将EAX扩展到RAX,并且因为相同的寄存器mov消除在Intel CPU上失败)。

有关前端/后端吞吐量瓶颈和延迟的更多信息,请参见X86的MOV真的可以“免费”吗?为什么我不能复制这个?

您可能会看到代码对齐的一些副作用,或者可能出现了类似于在没有优化的情况下编译时,添加冗余分配会加快代码的速度。的时髦沙桥家族存储转发延迟效应,因为您也在编译时禁用了优化功能,让编译器生成反优化代码,以便进行一致的调试,从而将循环计数器保存在内存中。(~6个循环循环-通过存储/重新加载来承载依赖链,而不是对一个普通的微小循环每时钟进行一次迭代。)

如果您的结果可以通过更大的迭代次数来重现,那么您所看到的可能有一些微观架构的解释,但它可能与您试图测量的任何内容无关。

当然,您还需要修复f3中的f3错误,以便在启用优化的情况下成功编译。在不告诉编译器的情况下破坏EAX,就会踩上编译器生成的代码。你没有解释你试图用它测试什么,所以IDK如果它是错误的话。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52992723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档