代码之家  ›  专栏  ›  技术社区  ›  Tony The Lion

测量执行单个指令的时间

  •  2
  • Tony The Lion  · 技术社区  · 14 年前

    有没有一种方法可以使用C或汇编程序,甚至C来精确测量执行一条加法指令需要多长时间?

    4 回复  |  直到 12 年前
        1
  •  11
  •   Jerry Coffin    14 年前

    是的,有点像,但它是不平凡的,产生的结果是 几乎 毫无意义,至少在最合理的现代处理器上是如此。

    在速度相对较慢的处理器上(例如,在Intel系列的原始奔腾处理器上,在大多数小型嵌入式处理器上仍然如此),您只需查看处理器的数据表,它就会(通常)告诉您期望的时钟节拍数。快速、简单和简单。

    在现代台式机(如Pentium Pro或更新版本)上,生活并非如此 几乎 很简单。这些CPU可以一次执行许多指令,并且只要它们之间没有任何依赖关系,就可以无序地执行它们。这意味着一条指令所花费的时间的整个概念几乎没有意义。执行一条指令所花费的时间可以并且将取决于它周围的指令。

    也就是说,是的,如果你真的想要,你可以(通常是——取决于处理器)测量一些东西,尽管它确实意味着多少还是一个相当大的问题。即使得到这样的结果 接近 然而,无意义而不是完全无意义并不是小事。例如,在Intel或AMD芯片上,您可以使用RDTSC自己进行定时测量。不幸的是,这可能会按上述顺序执行。为了得到有意义的结果,您需要用一条不能无序执行的指令(一条“序列化指令”)将其包围起来。最常见的选择是 CPUID 因为它是“用户模式”(即,环3)程序可用的少数串行化指令之一。不过,这也增加了一点麻烦:正如英特尔所记录的,处理器执行cpuid的头几次时间,可能比随后的时间要长。因此,他们建议您执行它 在你用它来序列化你的时间之前。因此,一般的序列运行如下:

    .align 16
    CPUID
    CPUID
    CPUID
    RDTSC
    ; sequence under test
    Add eax, ebx
    ; end of sequence under test
    CPUID
    RDTSC
    

    然后,您将其与执行相同操作的结果进行比较,但删除了正在测试的序列。当然,这遗漏了相当多的铁元素细节——至少你需要:

    1. 在每个cpuid之前正确设置寄存器
    2. 在第一个RDTSC之后将值保存在eax:edx中
    3. 从第一个RDTSC中减去第二个RDTSC的结果

    还要注意我插入的“对齐”指令——指令对齐也会影响时间,尤其是涉及到循环时。

        2
  •  2
  •   JustJeff    14 年前

    构造一个执行1000万次的循环,循环体中没有任何内容,并对其进行计时。保持时间作为循环所需的开销。

    然后再次执行同一个循环,这次在主体中测试代码。这个循环的时间减去开销(从空循环的情况下)是由于测试中的代码重复了1000万次而导致的时间。所以,除以迭代次数。

    显然,这个方法需要根据迭代次数进行调整。如果你所测量的是很小的,像一条指令,你甚至可能想要运行10亿次以上的迭代。如果它是一个重要的代码块,那么几千个就足够了。

    在单个汇编指令的情况下,汇编程序可能是执行该任务的正确工具,如果您熟悉内联汇编,则可能是C。其他人已经发布了更为优雅的解决方案来解决如何在没有重复的情况下获得测量结果,但是重复技术总是可用的,例如,一个没有其他人提到的好的定时指令的嵌入式处理器。

    但是请注意,在现代流水线处理器上,指令级并行可能会混淆结果。因为一次有多条指令在执行管道中运行,所以给定指令的n次重复所花费的时间与单个指令的n次重复所花费的时间不再正确。

        3
  •  0
  •   WonderWorker Sakal    12 年前

    好吧,如果您使用的是Windows、Linux、Unix、MacOS、AmigaOS等操作系统,以及后台已经在您的计算机上运行了许多进程的所有其他操作系统,那么您将遇到的问题将影响性能。计算指令实际时间的唯一真正方法是拆卸主板并使用外部硬件测试每个组件。这取决于您是真的想自己做这个,还是简单地找出一个典型的处理器版本实际运行的速度。像英特尔和摩托罗拉这样的公司在发布前对其芯片进行了广泛的测试,这些测试结果可以向公众公布。你需要做的就是问他们,他们会给你一张免费的CD-ROM(可能是一张DVD——胡说八道的书呆子),里面有结果。您可以自己做,但请注意,特别是英特尔处理器包含许多不再需要的冗余指令,更不用说必要的指令了。这会占用你很多时间,但我完全可以看到这样做的乐趣。如果它纯粹是为了帮助你自己的机器硬件在一个你正在做的个人项目中达到理论上的最大值,那么上面的Jeff的回答对于在现实条件下生成整洁的指令速度平均值是非常好的。

        4
  •  -3
  •   sizzzzlerz    14 年前

    没有,但是您可以根据加法指令所需的时钟周期数乘以CPU的时钟速率来计算它。添加的不同类型的参数可能会导致更多或更少的循环,但对于给定的参数列表,指令始终需要相同的循环数才能完成。

    那就是说,你为什么在乎?