使用计时器来测量代码性能

原创 2012年06月01日 09:34:09

在性能优化的时候,我们首先要做的是确定优化目标,即要定位最耗时的代码段 (在之前需要做架构和设计方案的优化,只有先确保房子盖的坚固没问题,才去考虑装修的事)。通常的做法就是加一些计时代码来测量代码的执行时间,看是否符合预期。那么本文就介绍一些与计时相关的一些知识。

可用的计时方法

  • 汇编指令RDTSC
  • GetTickCount()
  • timeGetTime()
  • QueryPerformanceCount()

关于RDTSC指令

  • Intel Pentium系列以后的所有处理器中都包含一个64 bit的寄存器TSC, 该寄存器保存CPU重置后经过的指令周期数。而RDTSC指令就是用来读取该寄存器值,通过EDX:EAX返回。并不是所有的处理器都包含该寄存器,如Cyrix 6x86。在Linux下,如果/proc/cpuinfo包含rdtscp,那么处理器支持TSC。
  • 当代码运行在多核或支持超线程的处理器环境,或支持休眠的操作系统中时,要小心使用RDTSC指令。因为多CPU下的TSC并不会保持同步,而系统休眠时会改变处理器的工作频率。
  • Intel Pentium Pro以后的处理器支持指令重排优化,也就是说RDTSC的执行顺序可能会被改变,从而计算了错误的指令执行时间。为了防止这种情况出现,可以先执行一些序列化指令,如CPUID。
  • 在Windows平台中,微软不建议使用TSC作为高精度的计时器,建议使用QueryPerformanceCounter()和QueryPerformanceFrequency()。Linux平台下有类似的函数,clock_gettime(CLOCK_MONOTONIC).

UINT64 readtsc(void) 
{
#if defined(__GNUC__)
#   if defined(__i386__)
    uint64_t x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
    return x;
#   elif defined(__x86_64__)
    uint32_t hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ((uint64_t)lo) | ((uint64_t)hi << 32);
#   else
#       error Unsupported architecture.
#   endif
#elif defined(_MSC_VER)
    __asm {
        return __rdtsc();
    }
#else
#   error Other compilers not supported...
#endif
}

将机器指令周期转换为时间

  • 首先要获取CPU的主频,一般忽略因系统休眠而产生的变频问题。在Windows下,可以读取注册表值:HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\N\~MHz,也可直接调用QueryPerformanceFrequency()。在Linux下,可以读取/proc/cpuinfo。
  • 时间差 = 指令周期差 / CPU主频

如何精确测量代码的运行时间

  • 根据你的需要来选择测量方法,GetTickCount()和timeGetTime()提供ms级精度,但是它们比RDTSC和QueryPerformanceCount()更稳定。
  • 减少代码被中断的机会:尽量减少需要测量的代码量(减少线程被切换的机会);尽量减小需要访问的内存(缓存命中、缺页、内存对齐等都会影响运行时间变化);提高线程优先级;
  • Cache warming: 将数据和指令提前放入缓存。
  • 多次测量取最小值。
  • QueryPerformanceCounter()使用多种方式来获取时间计数值,如在单处理器Intel平台中可能由RDTSC实现,其它平台下也可能通过专用的高精度硬件计时器。因此,QueryPerformanceCounter()本身的调用开销相对于RDTSC指令要高昂的多,在一些较小任务的计时操作时不得不考虑该因素。此外,在多处理器平台中,建议通过SetThreadAffinityMask()来限制线程的执行处理器,从而克服多处理器的时钟不同步问题。但是,SetThreadAffinityMask()会极大的影响系统的调度策略,一般会对性能造成影响,此时可以考虑SetThreadIdealProcessor().

推荐阅读


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

分别使用递归方法和非递归方法求斐波那契数列,并比较两者的运行速度(测量代码运行时间)

由运行时间可知,当数据量增大时,递归方法程序运行效率成为瓶颈,速度变得极为缓慢。 #include #include #include using namespace std; int Func...

Linux内存管理和性能学习笔记(一):内存测量与堆内存

第一篇 内存的测量 2.1. 系统当前可用内存 # cat /proc/meminfo MemTotal:        8063544 kB MemFree:    ...

性能测量工具类——TimeMeasureUtil & TimeMeasureProxy

TimeMeasureUtil:做单次时间测量。 1、为了能确保 startTime 和 endTime 都正确设置,因而采用实例对象来实现。每次测量是都能判断对象是否处在正确状态。 2、该类为工...
  • gqltt
  • gqltt
  • 2011-10-08 14:28
  • 630

Java 理论与实践: 动态编译与性能测量

动态编译情况下指标评测的风险   为动态编译的语言(例如 Java)编写和解释性能评测,要比为静态编译的语言(例如 C 或   C++)编写困难得多。在这期的 Java 理论与实...

Linux 下的一个全新的性能测量和调式诊断工具 Systemtap,第 1 部分: kprobe

http://www.ibm.com/developerworks/cn/linux/l-cn-systemtap1/index.html kprobe 的原理、编程接口、局限性和使用注...

python3 性能测量

环境$ cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core)工具$ sudo pip3 install gprof2dot $ s...

Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap

Systemtap的原理,Systemtap与DTrace比较,以及安装要求和安装步骤 杨 燚 (yang.y.yi@gmail.com), 计算机科学硕士, Intel 简介: 本系列文...

测量Web服务器的性能

一. 引言 性能测试与分析是软件开发过程中介于架构和调整的一个广泛并比较不容易理解的领域,更是一项较为复杂的活动。就像下棋游戏一样,有效的性能测试和分析只能在一个良好的计划策略和具备了对不可预料事件...

测量webView页面性能技术方案

测量webView页面性能(使用UiAutomator和性能监控工具)背景:俺双11会场测试的总指挥想要确认,在猫客的webview中填多少坑位合适,所以进行了如下操作并获取性能:1,进入webvie...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)