2013-03-10 32 views
1

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

我该如何着手测量这些值?

+2

在Linux上,'valgrind --tool = cachegrind'似乎很适合IYAM – sehe 2013-03-10 12:52:52

+0

现代处理器不仅执行多条指令每个周期,但时钟周期本身因节能\动态而变化rclock功能。但是,仍然可以轻松获得平均值 - 基准测试几个不同大小的数据集,知道已用时间和处理器时钟,无需任何特殊工具即可轻松获得近似估计值。 – dtech 2013-03-10 15:14:40

回答

2

现代处理器(即那些不是非常受约束的小于20岁左右的处理器)是超标量的,即它们一次执行多于一条指令(给定正确的指令排序)。最新的x86处理器将CISC指令转换为内部RISC指令,对其重新排序并执行结果,甚至有几个regster bank,因此使用“相同寄存器”的指令可以并行完成。目前没有任何合理的方式来定义“执行指令的时间”。

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

调整代码的最大性能开始于软件体系结构,继续进行程序组织,算法和数据结构选择(这里有一点缓存/虚拟内存意识也很有用),仔细的编程和(如最极端的措施来排除最后2%的性能)考虑因素,比如你提到的那些(以及另一个最喜欢的“重新组装” )。而排序就是这样,因为第一个等级为相同的成本提供了更多的性能。 措施挖掘之前,程序员出了名的找到瓶颈不可靠的。并考虑重组代码的性能成本,包括工作本身,说服自己这些复杂的代码是否正确,以及维护。鉴于计算机和人员的相对成本,极端的性能调整很少有意义(可能是流行操作系统中的重要代码路径,编译器生成的通用代码路径,但几乎没有其他地方)。

0

你可能会感兴趣的RDTSC x86指令,其内容为周期的相对数。

用于读取许多编译器柜台的实现见http://www.fftw.org/cycle.h

不过,我建议干脆用QueryPerformanceCounter的测量。实际循环次数很重要,调整代码通常只需要能够比较相对时间测量结果,而rdtsc却有很多缺陷(尽管可能不适用于您所描述的情况):

  • 在多处理器系统上,没有单个相干循环计数器值。
  • 现代处理器通常会调整频率,改变周期变化率。
+0

英特尔在几年前改变了rdtsc的规格说它返回实时,而不是周期。 – 2013-03-10 16:05:24

1

如果你在你的代码是打缓存,它更是创下内存真正感兴趣的,并且处理器小于其设计约10-15岁,那么在处理器性能计数器。您需要驱动程序级别的软件来访问这些寄存器,因此您可能不希望为此编写自己的工具。幸运的是,你不需要。

有像英特尔的VTune,AMD的CodeAnalyst和Linux的oprofile(可与AMD和Intel处理器兼容)的工具。

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

下一个更棘手的部分当然是试图解决这些问题,正如另一个答案中提到的,程序员并不总是擅长调整这些事情 - 而且这当然是耗时的,更不用说在X型处理器上运行良好的型号不一定能在Y型上运行得很快(早期的奔腾4有一些调整技巧,在AMD处理器上运行非常糟糕 - 如果另一方面,您可以调整AMD代码处理器的年龄,你会得到在同一代英特尔处理器上运行良好的代码!)