我试图在C中找到2个小函数的相对优点。一个通过循环添加,一个通过显式变量添加。这些功能本身无关紧要,但我希望有人教我如何计算周期以便比较算法。因此f1将需要10个周期,而f2将需要8个。这就是我想要做的那种推理。此时没有性能测量(例如gprof
实验),只是很好的旧指令计数。
这样做有好办法吗?有工具吗?文档?我正在编写C,在x86架构上使用gcc
进行编译。
答案 0 :(得分:7)
PAPI_get_real_cyc(3) - 返回自任意起点以来的总循环次数
答案 1 :(得分:5)
汇编程序指令rdtsc
(读取时间戳计数器)在EDX中重新调整:EAX注册当前CPU计时器计数,在CPU复位时启动。如果你的CPU以3GHz运行,那么一个滴答是1 / 3GHz。
编辑:
在MS窗口下,API调用QueryPerformanceFrequency
返回每秒的滴答数。
答案 2 :(得分:4)
不幸的是,对代码进行计时与在视觉上计算指令和时钟周期一样容易出错。无论是调试器还是其他工具,或者重新编译代码,重新运行10000000次并且时间紧迫,您可以更改缓存行中的位置,缓存命中和未命中的频率等等。您可以通过在被测试代码模块的上游添加或删除一些代码来缓解其中的一部分(导致添加和删除一些指令,从而更改程序的对齐方式,有时还会更改数据的对齐方式)。
凭借经验,您可以通过查看反汇编(以及高级代码)来了解性能。没有替代代码的时序,问题是代码容易出错的时间。这些经验来自许多经验,并试图完全理解为什么添加或删除一条指令没有产生或产生显着差异。为什么在被测模块的完全不同的不相关区域中添加或删除代码会在被测模块上产生巨大的性能差异。
答案 3 :(得分:2)
正如GJ写的另一个答案,我还建议使用“rdtsc”指令(而不是调用一些看起来正确的操作系统功能)。
我在这个主题上写了很多答案。 Rdtsc允许您在代码的“自然”执行环境中计算经过的时钟周期,而不是不得不求助于调用它一千万次,这可能是不可行的,因为并非所有函数都是黑盒子。
如果要计算经过的时间,可能需要关闭CPU上的节能。如果只是时钟周期的问题,则没有必要。
答案 4 :(得分:1)
如果您正在尝试比较性能,最简单的方法是将算法置于循环中并运行1000或1000000次。
一旦运行足够多次,可以看到小的差异,运行time ./my_program
,这将为您提供使用的处理器时间量。
这样做几次以获得抽样并比较结果。
尝试计算指令对x86架构没有帮助。这是因为不同的指令可能会花费大量不同的时间来执行。
答案 5 :(得分:1)
我建议使用模拟器。看看PTLsim它会给你一些周期数,除此之外你可能想看看一些工具来计算每个装配线的执行次数。
答案 6 :(得分:0)
使用gcc -S your_program.c
。 -S
告诉gcc生成程序集列表,该列表将命名为your_program.s
。
答案 7 :(得分:0)
周围有很多高性能时钟。 QueryPerformanceCounter是微软的。一般的技巧是运行数千个时间和时间的函数需要多长时间。然后除去循环次数所用的时间。您会发现每个循环的时间长度略有不同,因此对多次传递的测试是真正找出所需时间的唯一方法。
答案 8 :(得分:0)
这不是一个微不足道的问题。让我试着解释一下:
在不同的操作系统上有几种工具可以完全按照您的要求进行操作,但这些工具通常是更大环境的一部分。每条指令都被转换为一定数量的周期,具体取决于编译器运行的CPU以及程序执行的CPU。
我无法给你一个明确的答案,因为我没有足够的数据来传递我的判断,但我在数据库领域为IBM工作,我们使用工具来测量我们的代码和那些跟踪的周期和结构仅对程序编译和运行的实际CPU有效。 根据CPU的piplining的内部结构和编译器的有效性,生成的代码很可能仍然有缓存未命中以及您必须担心的其他区域。 (在这种情况下,您可能需要查看FDPR ......)
如果你想知道你的程序需要在你的CPU上运行多少个循环(用编译器编译),你必须了解CPU的工作原理以及编译器如何生成代码。
对不起,如果答案不足以解决你手边的问题。你说你在x86拱门上使用gcc。我会将汇编代码映射到你的CPU。 我相信你会找到一些领域,gcc本可以做得更好......