今天给大家带来最近工作中用到的关于gpu&cpu信息获取的节点的读取。
高通设备CPU采用cpufreq框架动态调节频率,相似的GPU这块采用了Linux devfreq框架进行调节。Devfreq有四种对频率的管理策略governor(框架规定,实际实现各厂商不同):
1、 performance:GPU会固定工作在其支持的最高频率上,以追求最高性能。
2、 powersave:GPU会固定工作在其支持的最低频率上,以追求最低的功耗。
3、 userspace:早期的管理策略,系统将变频策略的决策交给了用户态应用程序,并提供相应的接口供其使用。
4、 ondemand:userspace 是用户态的检测,效率低,而 ondemand 则是一个完全在内核态下工作并且能够以更加细粒度的时间间隔对系统负载情况进行采样分析的 governor 。
Qualcomm的GPU则使用的是他们自己的governor:msm-adreno-tz,他和ondemand有点相似,是在内核态根据GPU的负载来动态决定如何变频的。
高通给的可以手动调节GPU频率的接口为:
echo 1 >/sys/class/kgsl/kgsl-3d0/force_clk_on
echo 10000000 >/sys/class/kgsl/kgsl-3d0/idle_timer
echo performance >/sys/class/kgsl/kgsl-3d0/devfreq/governor
echo
参数设置解释:
1、echo 1 > force_clk_on是设置KGSL_PWRFLAGS_CLK_ON这个power_flags。使用echo freq > gpuclk时,是通过kgsl_pwrctrl_pwrlevel_change设置频率,它会判断KGSL_PWRFLAGS_CLK_ON这个power_flags,如果没有这个flag,可能就不会真正的设置频率。
2、echo 10000000 > idle_timer,,设置interval_timeout,默认值是80ms。
当系统启动的时候,在governorrestart的过程中,会重新初始化GPU所对应的频率,这样即使我们设置了我们想要的频率,最后也很快就被冲掉了,所以要把该interval_timeout设置为很大。
3、echo performance > devfreq/governor, 这时devfreq会为Adreno重新选择governor,也就是performance。这时它会使用GPU所支持的最大频率,而不考虑系统的负载。
默认的msm-adreno-tz机制会不停的动态更新频率,即使我们设置过频率也会被覆盖掉,这就是为什么直接设置频率无效的原因。而如果改成performance机制,这样它会使得Adreno动态的调整机制无效,我们的设置才会生效。
4、echo freq > gpuclk,简单的设置GPU的频率,一般是在200 000 000, 320 000 000和450 000 000之间,如果不对,就会就近选择这三者之一。
设备gpu信息的获取:
目录:
/sys/class/kgsl/kgsl-3d0
gpubusy 获取gpu使用率
gpuclk gpu工作频率
max_gpuclk 最大工作频率
gpu_available_frequencies 可用频率
force_clk_on 写入1,可以动态调节频率
devfreq ->../../devfreq/1c00000.qcom,kgsl-3d0
目录:
/sys/class/kgsl/kgsl-3d0/devfreq
available_frequencies //可用gpu频率
available_governors //可用gpu模式
cur_freq //当前工作频率
device ->../../../1c00000.qcom,kgsl-3d0
governor //当前工作设置的模式
max_freq //最大gpu工作频率
min_freq //最小gpu工作频率
polling_interval
power
subsystem ->../../../../../class/devfreq
target_freq
trans_stat
uevent
Gpu使用率获取:会得到两个值,(前一个/后一个)*100%=使用率
adb shell cat /sys/class/kgsl/kgsl-3d0/gpubusy
Gpu工作频率:
adb shell cat /sys/class/kgsl/kgsl-3d0/gpuclk
adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/cur_freq
Gpu最大、最小工作频率:
adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
Gpu可用频率
adb shell cat /sys/class/kgsl/kgsl-3d0/gpu_available_frequencies
adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/available_frequencies
Gpu可用工作模式:
adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/available_governors
Gpu当前工作模式:
adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/governor
Gpu最大、最小工作频率:
624000000
401800000
模式:msm-adreno-tz
Gpu可用频率
624000000 560000000 510000000401800000 315000000 214000000 133000000
(1)无论在灭屏、亮屏、还是在gpu消耗90%以上的条件下,GPU的工作模式都没有改变,全都是msm-adreno-tz。
(2)Gpu使用率、频率获取:
亮屏状态下:
对于tsvr Launcher应用,转动设备(场景复杂度不同),gpu使用率78-82%时,gpu频率510000000,560000000(很少出现);
Gpu使用率70%-75%时,gpu频率为401800000
小蜜蜂游戏:游戏运行过程中gpu使用率大约72-80%,频率为315000000 ,游戏结束不退出,gpu使用率 75%-85% 左右,gpu频率为560000000 || 640000000
VRhero应用:
运行过程中,gpu使用率78%-83%,gpu频率510000000,560000000,624000000,其中大部分时间段频率为560000000,624000000.
Vr Coaster应用:
运行过程中gpu使用率70-81%,gpu频率624000000,560000000,510000000.
Nijia切水果游戏:
游戏运行过程中Gpu使用率62%-71%,gpu频率214000000(极少出现),315000000,401800000,510000000
灭屏状态下:
灭屏前停留在主界面,GPU使用率在刚灭屏前3-5分钟gpu使用率会维持在75%-81%,gpu工作频率(401800000出现占80%,510000000出现次数占20%);后面会维持在70%-73%之间,GPU工作频率(401800000).
灭屏前停留在more app界面:
Gpu使用率维持在79-81%,gpu频率为315000000,
设备 sys/devices/system/cpu目录下可看到CPU有几个核心,如果四核分别命名为cpu0,cpu1,cpu2,cpu3,每个都是一个文件夹,进入可以查看每个核心的信息。
affected_cpus //当前工作核心 0 1 2 3
cpu0
cpu1
cpu2
cpu3
cpufreq
cpuidle
kernel_max
modalias
offline
online
possible
power
present
uevent
Cpu0文件夹内部:
cpufreq
cpuidle
online
power
rq-stats
subsystem
topology
uevent
cpufreq文件夹内部:
affected_cpus
cpuinfo_cur_freq
cpuinfo_max_freq
cpuinfo_min_freq
cpuinfo_transition_latency
related_cpus
scaling_available_frequencies//可用频率
scaling_available_governors//可用模式
scaling_cur_freq//当前频率
scaling_driver
scaling_governor//模式
scaling_max_freq //最大频率
scaling_min_freq//最小频率
scaling_setspeed
stats
cat /sys/devices/system/cpu/cpu0/online
文件中0表示该核心是offline状态的,关闭状态,1表示该核心是online状态的,开启状态。
echo "0" >/sys/devices/system/cpu/cpu0/online # 关闭该CPU
echo "1" > /sys/devices/system/cpu/cpu0/online# 打开该CPU
Cpu支持多种工作模式governor,模式主要对cpu工作频率进行修改,修改前需要查下CPU支持哪些模式:
adb shell cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
列举常见的几种工作模式:
interactive ondemand userspacepowersave performance
performance性能最好,不降频,cpu核心会一直保持在可用的最高频率,ondemand表示使用内核提供的功能,可以动态调节频率,powersvae表示省电模式,通常是在最低频率下运行,
userspace表示用户模式,在此模式下允许其他用户程序调节CPU频率。
echo "performance" >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
CPU的频率不可随意修改,scaling_available_frequencies文件列举了支持的频率,
adb shell cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
我的820设备工作频率:
200000 400000 533333 800000 9984001094400 1152000 1209600频率以Hz为单位的
echo "1209600" >/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
设置好后,我们可以通过scaling_cur_freq文件查看当前这个核心的工作频率
adb shell cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
最后我们也可以设置下CPU的最大和最小频率,只需要将需要设置的频率值写入scaling_max_freq和scaling_min_freq即可
echo "1152000 " >/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq # 设置最大频率
echo "200000" >/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq # 设置最小频率
设置时“最大值”需要大于等于“最小值”,如果把最小值设置为了最大值,则可用的频率只有最大值,相当于把模式调成performance。这里设置仅为某个,你需要对每个online的CPU核心都进行设置,同时以上对文件的修改均需要root权限。 可通过减少工作的核心数和限制CPU频率起到节省电量的目的,但是性能也是显著降低,但不能引起卡顿,引起了卡顿性能降低的太厉害了就不值得了。
下面的代码是gpu信息获得脚本,保存成x.pl文件可以获取gpu信息:
#!/usr/bin/perl -w
print "\n";
$gpumax = `adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/max_freq`;
$gpumin = `adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/min_freq`;
$gpuavaifre=`adb shell cat/sys/class/kgsl/kgsl-3d0/gpu_available_frequencies`;
printf("GPU 最大频率: %5.2f\n", $gpumax);
printf("GPU 最小频率: %5.2f\n", $gpumin);
printf("GPU 可用频率: %s\n", $gpuavaifre);
printf("===================================\n");
$lastgpumod="xxxxx";
while(1)
{
&busy;
print "\n";
sleep 1 ;
}
sub busy
{
$gpu3d = `adb shell cat/sys/class/kgsl/kgsl-3d0/gpubusy`;
$pct = 0.0;
if( $gpu3d =~ m/\s*(\d+)\s+(\d+)/)
{
if( $1 > 0 && $2 > 0)
{
$pct = $1 / $2 * 100;
}
printf("3D GPU Busy:%5.2f\n", $pct);
printf("\n");
}
$gpucurmod= ` adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/governor`;
if($lastgpumod ne $gpucurmod){
printf("GPU 当前模式: %s\n", $gpucurmod);
$lastgpumod=$gpucurmod;
}
# printf("GPU lastmoshi:%s\n", $lastgpumod);
$gpucurfreq = `adb shell cat /sys/class/kgsl/kgsl-3d0/gpuclk `;
$gpucurfreq2 = `adb shell cat/sys/class/kgsl/kgsl-3d0/devfreq/cur_freq`;
printf("GPU 当前频率: %s\n", $gpucurfreq);
#printf("GPU 当前频率2: %s\n", $gpucurfreq2);
}