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 命令查看。
有些注意点:
- rdtsc不管在32bit还是64bit,都是通过2个32位的寄存器返回的。
- 使用时最好看一下当前lscpu是不是有constant_tsc nostop_tsc的flag, 没有可能会有问题
- 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