linux之调度管理(11)-cpu动态调频总体架构

一、cpufreq的背景

 随着技术的发展,当前soc中的cpu主频一般都超过了1Ghz,而cpu的主频越高,其消耗的功耗也越大,这主要体现在以下两个方面:
(1)cpu的运行频率越高,则晶体管在单位时间内的开关次数就越多,与其相关的动态功耗也越高。

(2)为了保证数字电路的逻辑正确,cpu运行频率越高,则其所需的供电电压也越高

  但是系统在负载较轻时可能并不需要工作在最高主频上,特别是对于手机等可移动设备,这种性能浪费会直接影响其续航能力。为此若能根据系统的负载情况,动态调整cpu频率和电压,就能减少这部分功率消耗。cpufreq就是内核为支持这种能力而定义的一套管理框架。

二、cpufreq总体架构

cpufreq主要功能为动态调节cpu的频率和电压,为了达到这一目标,该框架需要考虑以下几个问题:
(1)确定每个cpu的频率调节范围,包括硬件支持的最大频率、最小频率,以及软件可调节的最大频率和最小频率等。在cpufreq中它可通过policy来管理

(2)在当前负载下,确定cpu应该工作于哪个频率,如简单地使cpu工作在最高频率以提供最高性能,或者使其工作在最低频率以降低功耗。但系统的负载是动态变化的,因此cpufreq还支持通过特定算法,在负载变化时动态调节cpu的频率。它可通过其governor组件实现

(3)确定cpu频率调节的周期及触发时机,以使其既不对系统有太大影响,又能较快地跟踪系统的负载变化。它是通过内核调度器和cpufreq模块共同完成的

(4)当待调节频率确定后,如何调用频率设置接口,实现实际的频率调节工作。它是通过其driver组件实现的

  除此以外,cpufreq还包含cpufreq stats,cpufreq qos,cpufreq notifier等辅助模块,其主要功能如下:
(1)cpufreq stats:用于搜集cpufreq的一些统计数据,如cpu在每个频点下的运行时间,总的切频次数等。

(2)cpufreq qos:该模块用于在cpufreq频率限制值发生改变时,向cpufreq模块发送一个通知,使其能及时调整到新的值

(3)cpufreq notifier:那些对cpu频率切换,或policy对应governor发生改变感兴趣的模块,可以向cpufreq注册一个通知。当以上事件发生时,cpufreq将会向其发送相关通知

  最后由于cpu的工作电压越高,其功耗也越大,因此我们希望cpu在切换到某一频率时,其电压也相应地切换到其可稳定工作的最低电压。为了得到电压和频率的关系,一般soc都会提供一些频点组合,cpufreq只会在这些规定的频点中切换。这些系统预置的频点叫做operation performance points(opp),它可通过如下例所示的dts文件配置:

cpu0: cpu@0 {
			...
			operating-points-v2 = <&cluster0_opp>;
			…
		};

	cpu1: cpu@1 {
			...
			operating-points-v2 = <&cluster0_opp>;
			...
		};
	cluster0_opp: opp_table0 {
		compatible = "operating-points-v2";
		opp-shared;

		opp00 {
			opp-hz = /bits/ 64 <533000000>;
			opp-microvolt = <700000>;
			clock-latency-ns = <300000>;
		};

		opp01 {
			opp-hz = /bits/ 64 <999000000>;
			opp-microvolt = <800000>;
			clock-latency-ns = <300000>;
		};

		opp02 {
			opp-hz = /bits/ 64 <1402000000>;
			opp-microvolt = <900000>;
			clock-latency-ns = <300000>;
		};

		opp03 {
			opp-hz = /bits/ 64 <1709000000>;
			opp-microvolt = <1000000>;
			clock-latency-ns = <300000>;
		};

		opp04 {
			opp-hz = /bits/ 64 <1844000000>;
			opp-microvolt = <1100000>;
			clock-latency-ns = <300000>;
		};
	};

内核抽象出了一个opp组件,用于管理这些电压和频率组合。当cpufreq执行频率切换时,则从opp表中选择一个最合适的频率电压值,然后通过opp接口,调用clk和regulator操作函数,完成实际的调频调压操作。综上所述,内核cpufreq模块的总体架构如下:

三、主要数据结构

3.1 cufreq_policy结构

cpufreq_policy结构包含了调频策略相关的频率范围等参数。它们包括其对应的调频策略、最大最小频率限制值,以及cpufreq qos参数等。以下为其结构体定义:

struct cpufreq_policy {
	cpumask_var_t	cpus;	
	cpumask_var_t	related_cpus; 
	cpumask_var_t	real_cpus;                                    (1)
	…
	unsigned int		cpu;                                  (2)
	struct clk			*clk;
	struct cpufreq_cpuinfo	cpuinfo;                              (3)

	unsigned int		min;
	unsigned int		max;
	unsigned int		cur;                                  (4)
	unsigned int		suspend_freq;                         (5)

	unsigned int		policy;                               (6)
	unsigned int		last_policy; 
 
	struct cpufreq_governor	*governor;                            (7) 
	void			*governor_data;

	char			last_governor[CPUFREQ_NAME_LEN]; 
	struct work_struct	update;

	struct freq_constraints	constraints;
	struct freq_qos_request	*min_freq_req;
	struct freq_qos_request	*max_freq_req;                        (8)

	struct cpufreq_frequency_table	*freq_table;
	enum cpufreq_table_sorting freq_table_sorted;                 (9)

	struct list_head    policy_list;                              (10)
	…
	struct cpufreq_stats	*stats;                               (11)
	void			*driver_data;                         (12)

	struct thermal_cooling_device *cdev;                          (13)
	struct notifier_block nb_min;
	struct notifier_block nb_max;                                 (14)
};

(1)cpus、related_cpus和real_cpus都用于表示使用该policy的cpu mask,它们的区别在于cpu的运行状态不同。其中cpus只包含当前处于online状态的cpu,related_cpus包含online和offline状态的cpu,而real_cpus则包含present状态的cpu

(2)cpufreq中每一种policy都通过一个cpu进行管理,它们可以是以上cpus掩码中的任意一个。由于内核支持cpu hotplug,因此若该cpu被下线以后,则需要重新选择一个cpu作为管理该policy的cpu

(3)cpuinfo结构体定义如下,它用于定义硬件支持的cpu最高、最低频率,以及切频的延迟时间。该频率值在系统运行过程中不会改变

struct cpufreq_cpuinfo {
	unsigned int		max_freq;
	unsigned int		min_freq;
	unsigned int		transition_latency;
}

(4)min、max表示当前cpufreq支持切换的最低和最高频率,该值可以与cpuinfo中规定的硬件频率范围不同,且不能超过该范围。当cpufreq qos改变频率范围时,这两个值就可能在系统运行过程中发生改变。而cur表示cpu的当前运行频率

(5)在suspend流程中需要被设置为该频率

(6)内核支持两种调频方式,一种是通过governor调频,它通过target_index或target回调执行调频操作。另一种是通过setpolicy回调调频,这时其调频策略将由policy的值确定,其取值可为 CPUFREQ_POLICY_POWERSAVE和CPUFREQ_POLICY_PERFORMANCE

(7)若使用governor调频方式,则该成员用于指定控制调频策略的governor

(8)这几个成员用于cpufreq qos特性,主要用于修改该policy支持的最低、最高频率

(9)freq_table用于保存该policy支持的所有频点,这些频点数据是在cpufreq驱动初始化时,从cpu对应的opp表中读取的。而freq_table_sorted用于指定这些频点的排序方式

(10)它用于将该policy挂到全局的policy链表中

(11)该结构体用于保存policy的统计数据

(12)用于保存驱动的私有数据

(13)由于cpu调频可以改变系统的功耗,因此thermal模块可通过调频方式为系统降温。这种方式下,cpufreq就作为thermal模块的降温设备

(14)这两个通知将被注册到qos的通知链中,当cpufreq的最大、最小频率发生改变时,qos模块将分别调用这两个通知

3.2 cpufreq_governor结构体

        cpufreq governor的主要功能是根据其相应的控制策略,为cpu选择一个合适的运行频率,该流程实际上是由governor的start接口向调度子系统注册一个回调函数,并由调度子系统触发调频操作时执行的。

cpufreq_governor结构体主要提供了一组回调函数,用于控制特定governor的相关流程:

struct cpufreq_governor {
	char	name[CPUFREQ_NAME_LEN];                                 (1)
	int	(*init)(struct cpufreq_policy *policy);                 (2)
	void	(*exit)(struct cpufreq_policy *policy);                 (3)
	int	(*start)(struct cpufreq_policy *policy);                (4)
	void	(*stop)(struct cpufreq_policy *policy);                 (5)
	void	(*limits)(struct cpufreq_policy *policy);               (6)
	ssize_t	(*show_setspeed)	(struct cpufreq_policy *policy,
					 char *buf);                  
	int	(*store_setspeed)	(struct cpufreq_policy *policy,
					 unsigned int freq);            (7)
	struct list_head	governor_list;                          (8)
	struct module		*owner;
	u8			flags;                                  (9)
}

(1)该governor的名字

(2)初始化一个governor时的回调函数

(3)退出一个governor时的回调函数

(4)启动一个governor的回调函数

(5)停止一个governor的回调函数

(6)若一个policy的最高或最低频率值发生改变,会调用本函数,用于判断cpu当前运行频率是否已不在新的频率范围之内。如果是的话,就将其当前频率设置到新频率范围之内

(7)show_setspeed和store_setspeed分别为sysfs用于读取和修改频率的接口

(8)用于将该governor挂到全局governor链表的节点

(9)用于保存该governor的标志

3.3 cpufreq_driver结构

        cpufreq_governor会根据governor特定的策略,计算得到cpu待设置频率对应的频点,而频率设置流程需要cpufreq 驱动完成。cpufreq驱动主要包含一组回调函数,而特定驱动函数只需要实现这些回

<think>嗯,用户想了解自动驾驶算法在ARM平台上的嵌入式开发部署步骤。首先,我需要确定自动驾驶算法的基本构成,可能包括感知、定位、决策和控制等模块。然后,ARM平台的特点需要考虑,比如计算资源有限、功耗低,可能需要优化算法。 接下来,步骤可能包括算法设计、仿真测试、ARM平台适配、性能优化、部署和测试。要注意的是,嵌入式开发通常需要交叉编译,可能需要使用特定的工具链。另外,实时性要求高,可能需要实时操作系统或优化调度策略。 用户可能关心如何将复杂的算法移植到资源受限的ARM设备上,可能需要模型压缩、量化或使用轻量级框架。比如TensorFlow Lite或ONNX Runtime。同时,硬件加速如NEON指令集或GPU加速也可能涉及。 还需要考虑传感器数据的处理,比如摄像头、雷达的数据输入在ARM上的处理效率。可能涉及驱动开发、中间件选择,如ROS2或其他嵌入式中间件。 安全性也是重点,功能安全和信息安全的保障措施。可能涉及ISO 26262标准的部分内容,虽然嵌入式部署可能简化一些流程,但基础的安全机制仍需考虑。 用户可能希望得到一个从算法开发到实际部署的全流程概述,重点在ARM平台的挑战和解决方案。需要分步骤解释,每个阶段的关键任务和常用工具,比如仿真用CARLA,部署用Docker或直接烧录到硬件。 最后,确保语言通俗易懂,结构清晰,帮助用户建立系统化的理解,可能还要提到测试验证的重要性,包括单元测试、集成测试和实车测试等环节。</think>自动驾驶算法在ARM平台嵌入式开发部署可分为以下六个关键步骤,每个步骤均需结合嵌入式系统特点进行针对性优化: 1. **算法轻量化改造** - 模型压缩:采用知识蒸馏(如DistilBERT)、通道剪枝(Channel Pruning)技术 - 量化部署:使用TensorFlow Lite INT8量化或NCNN FP16混合精度 - 算子重构:将3D卷积替换为深度可分离卷积(Depthwise Separable Conv) - 框架适配:移植至Tengine/MNN等嵌入式推理框架 2. **ARM硬件适配层开发** - 指令集优化:针对Cortex-A系列CPU的NEON指令手工汇编优化 - 异构计算:通过OpenCL/Vulkan调度Mali GPU加速 - 内存管理:设计双缓冲机制(Double Buffering)减少DMA传输延迟 - 功耗控制:实现DVFS动态调频(如通过Linux cpufreq子系统) 3. **实时系统集成** - RTOS定制:在FreeRTOS或Zephyr中实现任务优先级抢占调度 - 时间同步:采用PTPv2协议实现μs级多传感器同步 - 中断优化:设计嵌套中断控制器(NVIC)响应策略 - 确定性保障:通过WCET(最坏执行时间)分析方法确保实时性 4. **传感器数据流水线** - 数据采集:设计CSI-2接口的ISP图像信号处理流水线 - 预处理加速:基于OpenVX实现硬件加速的图像畸变校正 - 数据融合:开发基于Kalman Filter的ARM NEON优化实现 - 低延迟传输:采用共享内存+环形缓冲区(Ring Buffer)架构 5. **安全机制嵌入** - 功能安全:集成AUTOSAR的BSW模块实现ASIL-B等级 - 异常检测:部署Arm TrustZone技术的安全监控域 - 看门狗系统:设计三级看门狗(硬件/OS/应用级)联锁机制 - 加密通信:集成Arm CryptoCell-312的TLS加速引擎 6. **部署验证体系** - 虚拟化测试:利用QEMU进行指令级仿真验证 - 功耗分析:使用Arm Energy Probe进行微焦耳级能耗测量 - 热测试:通过红外热成像仪进行散热评估 - 场景回灌:基于ROS2的日志回放测试(使用ARM-FPGA混合架构) 典型开发工具链配置示例: ```bash # 交叉编译工具链配置 export CC=/opt/gcc-arm-11.2/bin/arm-none-linux-gnueabihf-gcc export CXX=/opt/gcc-arm-11.2/bin/arm-none-linux-gnueabihf-g++ # Tengine部署示例 ./tm_convert -f onnx -m yolov5s.onnx -o yolov5s.tmfile ./tm_classification -m yolov5s.tmfile -i test.jpg -g 224,224 -s 0.017,0.017,0.017 ``` 关键性能优化指标参考值: - 推理延迟:≤80ms(基于Cortex-A72 @2.0GHz) - 内存占用:<256MB(含模型权重+中间张量) - 功耗表现:≤5W(典型复杂场景下) - 温度范围:-40℃~85℃(符合AEC-Q100标准) 该过程需要持续进行设计迭代,建议采用CI/CD流水线实现自动化部署验证,典型迭代周期应控制在2周以内以适应快速算法更新需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值