x86下的tsc计时器

tic-toc.s对外提供两个接口,void tic(void), uint64_t toc(void), 用法基本类似matlab的tic toc函数,toc函数返回的是cycles, 转换成时间需要除cpu tsc的频率,tsc频率一般不是cpu主频,而是最大频率的1/2,(cpu有最大和睡眠频率),获取tsc的频率可以通过接口dmesg | grep tsc bash 命令查看。

有些注意点:

  1. rdtsc不管在32bit还是64bit,都是通过2个32位的寄存器返回的。
  2. 使用时最好看一下当前lscpu是不是有constant_tsc nostop_tsc的flag, 没有可能会有问题
  3. rdtsc返回的是机器开机之后总的cycles数,以2GHz为例,uint64存储时钟,约292年才回出现反转,所以基本不用担心反转的问题。
.section .data
.local s_time
.type s_time,@object
s_time:
 .zero 8
.size s_time, 8

.text
.global tic
.type tic,@function
tic:
 rdtsc
 leaq s_time(%rip), %rbx
 movl %edx, 4(%rbx)
 movl %eax, (%rbx)
 ret
.size tic,.-tic

.text
.global toc
.type toc,@function
toc:
 pushq %rbp
 movq %rsp, %rbp
 subq $8, %rsp
 rdtsc
 movl %edx, 4(%rsp)
 movl %eax, (%rsp)
 movq s_time(%rip), %rbx
 movq (%rsp), %rax
 subq %rbx, %rax
 #movq %rbx, s_time(%rip)
 addq $8, %rsp
 popq %rbp
 ret
.size toc,.-toc

一个main函数使用tic、toc的例子,

#include <stdint.h>
#include <stdio.h>
void tic(void);
uint64_t toc(void);

int main() {
 tic();
 int ans =0;
 for(int i=0; i<100; i++) ans += i;
 printf("%lu cycles passed\n", toc());

 tic();
 ans =0;
 for(int j=0; j<3000; j++)
 for(int i=0; i<1000000; i++) ans += i;
 printf("%.2f us passed\n", (double)toc()/2.112e3);

 return 0;
}

参考
【1】https://blog.csdn.net/Once_day/article/details/130959295
【2】https://blog.csdn.net/ithiker/article/details/119981737

posted @ 2024-12-15 17:17  zwlwf  阅读(7)  评论(0编辑  收藏  举报