如何测量读/循环或指令/循环?

时间:2013-03-10 12:11:56

标签: c++ c performance caching metrics

我想彻底测量和调整我的C / C ++代码,以便在x86_64系统上使用缓存更好地执行。我知道如何使用计数器(我的Windows机器上的QueryPerformanceCounter)来测量时间,但我想知道如何测量每个周期的指令或每个周期相对于工作集的读/写。

我应该如何衡量这些价值?

3 个答案:

答案 0 :(得分:2)

现代处理器(即那些不太受约束且小于约20年的处理器)是超标量的,即,它们一次执行多于一个指令(给定正确的指令排序)。最新的x86处理器将CISC指令转换为内部RISC指令,对它们进行重新排序并执行结果,甚至还有几个寄存器库,因此可以并行执行使用“相同寄存器”的指令。今天没有任何合理的方法来定义“指令执行所需的时间”。

当前的CPU 比内存更快(几百条指令是访问内存的典型成本),它们都严重依赖缓存来提高性能。然后你有各种有趣的核心共享(或不共享)部分缓存,...

调整代码以获得最佳性能从软件架构开始,继续进行程序组织,算法和数据结构选择(这里一小部分缓存/虚拟内存感知也很有用),仔细编程和(最极端的措施)挤出最后2%的性能)考虑因素,如你提到的(和另一个最喜欢的,“重写汇编”)。排序是一个因为第一级别以相同的成本提供更多性能。在深入挖掘之前,测量,程序员在查找瓶颈方面是非常不可靠的 。并且考虑重新组织代码以提高性能的成本,无论是在工作本身,还是说服自己这个复杂的代码是正确的,还是维护。考虑到计算机和人员的相对成本,极端性能调优很少有意义(可能对于流行操作系统中的大量代码路径,在编译器生成的公共代码路径中,但几乎没有其他地方)。

答案 1 :(得分:1)

如果你真的对你的代码在什么地方遇到缓存以及它在内存中的位置感兴趣,并且处理器的设计时间不到10到15年,那么处理器中就会有性能计数器。您需要驱动程序级软件来访问这些寄存器,因此您可能不想为此编写自己的工具。幸运的是,你不必这样做。

有来自英特尔的VTune,来自AMD的CodeAnalyst和适用于Linux的oprofile(适用于AMD和英特尔处理器)等工具。

有一系列不同的寄存器可以计算实际完成的指令数,即处理器等待的周期数。您还可以计算诸如"内存读取次数","缓存未命中数"," TLB未命中数","数FPU指令"。

下一个更棘手的部分当然是尝试解决这些问题中的任何问题,正如另一个答案中所提到的,程序员并不总是擅长调整这些事情 - 而且它是&#39 ; s肯定是耗时的,更不用说在X型处理器上运行良好的东西不一定能在Y型上快速运行(早期的奔腾4有一些调整技巧在AMD处理器上非常糟糕 - 如果另一方面,你调整那个时代的AMD处理器的代码,你得到的代码在同一代英特尔处理器上运行良好!)

答案 2 :(得分:0)

您可能对rdtsc x86指令感兴趣,该指令读取相对循环次数。

有关在许多编译器中读取计数器的实现,请参阅http://www.fftw.org/cycle.h

但是,我建议只使用QueryPerformanceCounter进行测量。实际的循环次数很少是很重要的,调整代码通常只需要能够比较相对时间测量,而rdtsc有很多陷阱(尽管可能不适用于你描述的情况):

  • 在多处理器系统上,没有一个相干周期计数器值。
  • 现代处理器通常会根据周期变化率调整频率,改变时间变化率。