ARM 上的定时器
如果测量的事件超过一微妙,可以使用软件的系统定时器,在 Linux 系统上,可以通过clock_gettime
系统调用访问系统定时器。在 C++ 中访问系统定时器的标准方式是使用std::chrono
:
1 |
|
如果测量的事件是纳秒级到一分钟,可以读取CNTVCT_EL0
寄存器,这是一种硬件定时器,被实现为一个硬件寄存器。时间戳计数器是单调的,并且速率恒定,即它不受频率变化的影响。每个 CPU 都有自己的时间戳计数器,它就是所经过的参考周期数。可以认为是 ARM 上 rdtsc
的实现:
1 | static inline uint64_t |
注:代码来源https://blog.csdn.net/z20230508/article/details/136741584
但是读 CNTVCT_EL0
的方法也不能精确到 cpu cycle,因为其频率通常比 cpu 频率低很多,譬如在天玑9400的机器(我用的是 vivo 的 X200 Pro)上,TSC 的频率仅为13MHZ,但是 CPU 频率都是 GHZ 为单位的。
我查阅资料,看到可以通过读取 PMCCNTR_EL0
寄存器来达到 cpu cycle 精度定时,但是这个寄存器默认用户态不可访问,需要内核打开,在 6.6 内核上,按照https://ilinuxkernel.com/?p=1755目前我没有打开成功。而且在手机上大小核并且频率还会动态变化,各个cpu的频率不一样会导致计数不准确,所以用这个方法需要将测试用例绑核并且固定核的频率。