Porting x86架构的rdtsc函数到ARM64架构的方法

极术社区 2021-07-08 18:21:32

首发极术社区,作者James 张

x86架构下,我们要想在用户态通过定时器方式来对代码执行时间做衡量可以使用Time Stamp Counter(TSC)寄存器,可精确到CPU Cycle级别。

由于ARM架构支持的是完全不同的指令集,因此获取TSC的方法存在差异。近些年来随着arm架构的广泛使用,以前基于x86架构运行的应用,现在要跑在ARM架构下,当运行的应用需要获取TSC时,则需要汇编级的代码移植,这对上层应用编写者提出了不小的挑战。为此,本文分享Arm64架构下如何获取TSC的方法,以方便大家移植使用。

首先,我们介绍一种利用Arm64架构的System counter来实现提供TSC的方法。System counter是Arm64下独立于CPU core的计数器,在系统上电时,会给此计数器设置固定的频率。一个映射system counter计数器内容的寄存器为CNTVCT_EL0,可在用户态下读取此寄存器获取counter值。而CNTFRQ_EL0保存的是counter的频率值。

以c/c++语言为例给出实现代码:

static inline uint64_t 
arm64_cntvct(void)
{
   uint64_t tsc;
   asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));
   return tsc;
}

static inline uint64_t
arm64_cntfrq(void)
{
   uint64_t freq;
   asm volatile("mrs %0, cntfrq_el0" : "=r" (freq));
   return freq;
}

static inline uint64_t
rdtsc(void)
{
   return arm64_cntvct();
}

通过以上函数实现获取counter值及频率值,我们是可以实现对某些任务做相应的时间衡量的。但是system counter的精度一般不会超过100MHz,一般是达不到CPU cycle级别的精度。

考虑到利用system counter来实现提供TSC的方法可能满足不了某些任务的需求,我们给出方法二来实现提供TSC并能达到CPU cycle级别的精度要求。此方法是借助PMU系列寄存器中的PMCCNTR_EL0,读取此寄存器就可以知道当前CPU已运行了多少 cycle。
以c/c++语言为例给出实现代码:

static inline uint64_t
arm64_pmccntr(void)
{
   uint64_t tsc;
   asm volatile("mrs %0, pmccntr_el0" : "=r"(tsc));
   return tsc;
}

static inline uint64_t
rdtsc(void)
{
   return arm64_pmccntr();
}

通过以上函数实现,我们获取的TSC可以达到CPU cycle级别的精度。但是Linux系统下,用户态默认没有开启对PMCCNTR_EL0寄存器的读权限,需要通过内核态使能后才能读取。

以c/c++语言为例给出核心使能代码:

static void enable_pmu_pmccntr(void)
{
   u64 val = 0;
   asm volatile("msr pmintenset_el1, %0" : : "r" ((u64)(0 << 31)));
   asm volatile("msr pmcntenset_el0, %0" :: "r" ((u64)(1 << 31)));
   asm volatile("msr pmuserenr_el0, %0" : : "r"((u64)(1 << 0) | (u64)(1 << 2)));
   asm volatile("mrs %0, pmcr_el0" : "=r" (val));
   val |= ((u64)(1 << 0) | (u64)(1 << 2));
   isb();
   asm volatile("msr pmcr_el0, %0" : : "r" (val));
}

详细使能步骤可参考如下链接:
[https://ilinuxkernel.com/?p=1755]

...全文
7183 1 打赏 收藏 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN-Ada助手 2023-01-13
  • 打赏
  • 举报
回复
您可以前往 CSDN问答-编程语言 发布问题, 以便更快地解决您的疑问
含训练好的YOLO权重与PyQt可视化检测界面,开箱即用,毕业设计/课程设计可直接上手。 【数据集概况】 · 检测类别(中文):[冲浪者(surfer)] · 训练集:438 张 · 验证集:125 张 · 测试集:63 张 · 总计:626 张 该数据集针对海滩冲浪场景进行精心构建,全面覆盖冲浪者在不同海浪条件下的动态表现,为海洋运动安全监测与行为分析提供了高价值数据资源,显著提升了相关领域的研究与应用水平。 该数据集训练集438张、验证集125张、测试集63张,分布科学合理,训练集规模充足以支持模型充分学习,验证集与测试集比例恰当,有效保障模型评估的准确性和可靠性。 该数据集标注质量卓越,所有冲浪者目标均被精确标注,边界框紧密贴合目标轮... 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 91 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.8359** mAP50-95 | 0.4031 Precision | 0.8209 Recall | 0.7764 train/box_loss | 1.7868 train/cls_loss | 0.8077 val/box_loss | 1.7200 val/cls_loss | 0.7941 【训练过程分析】 91 轮训练后 mAP50 为 0.8359,模型基本收敛但还有提升余地。Loss 曲线下降正常,后期趋于平缓。mAP50-95 为 0.4031,和 mAP50 差距 0.43,定位精度是主要短板。 【模型性能评估】 Precision 0.8209、Recall 0.7764,精度高于...
内容概要:本文介绍了基于神经网络的数据驱动迭代学习控制(ILC)算法,旨在解决具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车路径跟踪问题,并提供了完整的Matlab代码实现。该方法融合了神经网络强大的非线性逼近能力与迭代学习控制在重复任务中不断优化性能的优势,能够在系统动态模型未知的情况下,通过多次运行轨迹的误差反馈,逐步提升控制器的跟踪精度。文中系统阐述了算法的理论基础、控制架构设计、神经网络的训练机制及其与ILC框架的集成方法,重点攻克了无人车在复杂、不确定环境下实现高精度、强鲁棒性轨迹跟踪的技术难题。; 适合人群:具备一定自动控制理论基础和Matlab编程能力,从事无人驾驶、智能控制、机器人或优化算法研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于无人车、机器人等需要执行周期性或重复路径任务的智能系统中,实现高精度的轨迹跟踪;②为解决非线性、强耦合、模型不确定系统的控制问题提供一种先进的数据驱动解决方案;③目标是帮助读者深入理解并掌握数据驱动的ILC与神经网络深度融合的前沿控制策略,完成从理论分析、算法设计到仿真实践的全流程学习。; 阅读建议:学习者应重点关注算法的迭代学习律设计、神经网络权重的在线更新机制以及二者协同工作的原理,结合所提供的Matlab代码进行仿真调试,通过改变期望轨迹、初始条件、系统噪声和外部干扰等参数,全面验证算法的收敛性、鲁棒性和泛化能力。

31,524

社区成员

发帖
与我相关
我的任务
社区描述
欢迎加入极术社区,共创中国智能计算生态。社区提供智能计算领域的资讯,鼓励技术写作和问答互助,致力促进中国芯片技术的合作创新。地址:https://aijishu.com
人工智能 企业社区
社区管理员
  • 极术社区
  • 闫辉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧