呵呵呵呵呵

萝莉有三好,柔体 轻音 易推倒。女神有三宝,干嘛 呵呵 去洗澡。宅男有三好:Dota 基友 破电脑。


通过机器指令RDTSC读取TSC时间戳代码

通过机器指令RDTSC读取TSC时间戳代码

从Intel Pentium开始,很多80x86微处理器都引入一个运行在时钟周期级别的时间戳计数寄存器TSC(Time Stamp Counter)。该寄存器以64位无符号整型数的格式,记录CPU上电以来所经过的时钟周期数,并在每个时钟信号(CLK,即处理器中用于接收外部振荡器的时钟信号输入引线)到来时加一。目前的处理器主频非常高,因此该寄存器可达到纳秒级的计时精度(在1GHz处理器上每个时钟周期为1纳秒)。

关于周期计时的最大长度,可用下列公式简单估算:

自CPU上电以来的秒数 = RDTSC读出的周期数 / CPU主频速率(Hz)

若处理器主频为1GHz,则大约需要583~584年,才会从2的64次方(64位无符号整数所能表达的最大数字+1)绕回到0,所以大可不必考虑溢出问题。

通过机器指令RDTSC(Read Time Stamp Counter)可读取TSC时间戳值,并将其高32位存入EDX寄存器,低32位存入EAX寄存器。现有的C/C++编译器多数不直接支持使用RDTSC指令,需用内嵌汇编的方式访问。以下给出常见的几个RDTSC宏定义和封装函数:

 #define RDTSC(low, high)  asm volatile("rdtsc" : "=a" (low), "=d" (high))
 #define RDTSC_L(low)      asm volatile("rdtsc" : "=a" (low) : : "edx")
 #define RDTSC_LL(val)     asm volatile("rdtsc" : "=A" (val))
 
 /* Set *hi and *lo to the high and low order bits of the cycle counter.
  * Implementation requires assembly code to use the rdtsc instruction. */
 void AccessCounter(unsigned *hi, unsigned *lo){
     asm volatile("rdtsc; movl %%edx,%0; movl %%eax, %1"
     : "=r" (*hi), "=r" (*lo)
     : /* No input */
     : "%edx", "%eax");
 }
 
 typedef unsigned long long cycle_t;
 /* Record the current value of the cycle counter. */
 inline cycle_t CurrentCycle(void){
     cycle_t tRdtscRes;
     asm volatile("rdtsc" : "=A" (tRdtscRes));
     return tRdtscRes;
 }
 inline cycle_t CurrentCycle2(void){
     unsigned hi, lo; 
     asm volatile ("rdtsc" : "=a"(lo), "=d"(hi)); 
     return ((cycle_t)lo) | (((cycle_t)hi)<<32); 
 }

其中,asm/volatile是GCC扩展的__asm__/__volatile__内嵌汇编关键字宏定义,若不考虑兼容性可直接采用不加下划线的格式。

通过TSC寄存器值可计算处理器主频,或测试处理器其他处理单元的运算速度。例如,一个周期计数相当于1/(处理器主频Hz数)秒,若处理器主频为1MHZ,则TSC值会在1秒内增加1000,000。在时间间隔1秒的前后分别记录TSC值,然后求差并除以1000,000,即可计算出以MHZ为单位的主频。代码如下:

 #include <unistd.h>  //alarm, pause
 #include <sys/types.h>
 #include <signal.h>  //signal, kill
 
 cycle_t tStart = 0, tEnd = 0;
 void TimingHandler(int signo){
     tEnd = CurrentCycle();
     printf("CPU Frequency: %lldMHz\n", (tEnd-tStart)/1000000);
     kill(getpid(), SIGINT);
 }
 
 void CalcCpuFreq(void){
     signal(SIGALRM, TimingHandler);
     tStart = CurrentCycle();
     alarm(1);
     while(1)
         pause();
 }

周期计数方式的优点是:

1) 高精度。在目前处理器上可获得纳秒级的计时精度。

2) 成本低。Pentium以上的i386处理器均支持RDTSC指令(其他平台也有类似指令),且访问开销极小。

其缺点是:

1) 周期计数指令因处理器平台和实现机制而异,没有与平台无关的统一访问接口,需借助内嵌汇编。

2) 因精度较高,故数据抖动比较厉害。RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。

此外,周期计数方式只测量经过的时间,不关心哪个进程使用这些周期。机器负载、进程上下文切换、高速缓存命中率以及转移预测等都会影响计数值,导致过高估计程序的真实运行时间。《深入理解计算机系统》一书第9章中,深入讨论了这些因素对计时的影响以及尽可能获取精确计时的方法。
    

更多内容:

linux中使用getrusage获取系统资源的占用信息
fopen mode中a与a+区别
linux ubuntu下解压缩tar.xz文件
Source Insight最新版3.50.0082下载与注册码
Windows 10无线网卡无法启动承载网络

本文链接地址:http://www.hehehehehe.cn/i/816.html