То есть демон динамически меняющий параметры cpufreq в зависимости от различных факторов (на данный момент только sensors, заряд батареи в процессе)
Это рабочий конфиг
Показать
-- example configuration for Intel(R) Core(TM)2 Duo CPU T5800 @ 2.00GHz
require "math" --require "io"
functionvery(n)return n^2end functionnot_very(n)return n^0.5end functionnorm(n)if n >=0.5then return true else return false end end
fuzzy_and = math.min
fuzzy_or = math.max functionfuzzy_not(n)return1.0- n end
profiles = {
default =function() -- fan control example --f = io.output(" put here path to the fan control ","w") --f:write(math.floor(255 * sensor("cpu", "hot"))) --f:flush() --f:close() ifnorm(fuzzy_or(sensor("cpu0","hot"),sensor("cpu1","hot")))then --print("hot") if notcpufreq({0,1},low_policy)then lpmdQuit() return end elseifnorm(fuzzy_or(sensor("cpu0","warm"),sensor("cpu1","warm")))then --print("warm") if notcpufreq({0,1},norm_policy)then lpmdQuit() return end elseifnorm(fuzzy_and(sensor("cpu0","cold"),sensor("cpu1","cold")))then --print("cold") if notcpufreq({0,1},perf_policy)then lpmdQuit() return end end end }
На lua только файл конфигурации, остальное написано на Си.
В данном состоянии прилично обгоняет cpufreqd как по cputime, так и по потреблению памяти.
Хочется комментариев.
Открытый естественно, просто я начал его меньше месяца назад, и всё ещё очень сырое, а я всё ещё в творческом поиске, думаю, вот, изменить формат конфигурации. Сегодня, наверное, подчищу и выложу.
Просто хотелось бы узнать, нужно ли.
Качайте здесь, данная версия даже не бета, а так пробный вариант, к тому же я не являюсь проффесиональным программистом, поэтому попрошу какашками не кидаться.
Выложил специально для linuxforum.ru, и скоро удалю.
В цикле все сообщения выдаёт в syslog, если всё правильно, то должно быть вроде:
Показать
text
Mar 3 13:38:12 localhost lpmd[3242]: set active profile: default
Mar 3 13:38:12 localhost lpmd[3242]: set poll interval: 10
Mar 3 13:38:12 localhost lpmd[3242]: find sensor "cpu0" label: "temp1" value: 43.000000
Mar 3 13:38:12 localhost lpmd[3242]: find sensor "cpu1" label: "temp2" value: 43.000000
Mar 3 13:38:12 localhost lpmd[3242]: set cpufreq: 0, min: 800000, max: 2000000, conservative
Mar 3 13:38:12 localhost lpmd[3242]: set cpufreq: 1, min: 800000, max: 2000000, conservative
Mar 3 13:38:13 localhost lpmd[3242]: get sensor "cpu0" value: 43.000000
Mar 3 13:38:13 localhost lpmd[3242]: get sensor "cpu1" value: 43.000000
Mar 3 13:38:13 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:38:13 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
Mar 3 13:38:14 localhost lpmd[3242]: get sensor "cpu0" value: 43.000000
Mar 3 13:38:14 localhost lpmd[3242]: get sensor "cpu1" value: 43.000000
Mar 3 13:38:14 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:38:14 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
burnMMX x 2
text
Mar 3 13:38:40 localhost lpmd[3242]: get sensor "cpu0" value: 47.000000
Mar 3 13:38:40 localhost lpmd[3242]: get sensor "cpu1" value: 47.000000
Mar 3 13:38:40 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:38:40 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
Mar 3 13:38:41 localhost lpmd[3242]: get sensor "cpu0" value: 48.000000
Mar 3 13:38:41 localhost lpmd[3242]: get sensor "cpu1" value: 48.000000
Mar 3 13:38:41 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:38:41 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
Mar 3 13:38:42 localhost lpmd[3242]: get sensor "cpu0" value: 51.000000
Mar 3 13:38:42 localhost lpmd[3242]: get sensor "cpu1" value: 51.000000
Mar 3 13:38:42 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:38:42 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
...
Mar 3 13:39:03 localhost lpmd[3242]: get sensor "cpu0" value: 56.000000
Mar 3 13:39:03 localhost lpmd[3242]: get sensor "cpu1" value: 56.000000
Mar 3 13:39:03 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:39:03 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
Mar 3 13:39:04 localhost lpmd[3242]: get sensor "cpu0" value: 56.000000
Mar 3 13:39:04 localhost lpmd[3242]: get sensor "cpu1" value: 57.000000
Mar 3 13:39:04 localhost lpmd[3242]: set cpufreq: 0, min: 800000, max: 1600000, conservative
Mar 3 13:39:04 localhost lpmd[3242]: set cpufreq: 1, min: 800000, max: 1600000, conservative
Mar 3 13:39:05 localhost lpmd[3242]: get sensor "cpu0" value: 52.000000
Mar 3 13:39:05 localhost lpmd[3242]: get sensor "cpu1" value: 52.000000
Mar 3 13:39:05 localhost lpmd[3242]: set cpufreq: 0, min: 800000, max: 2000000, conservative
Mar 3 13:39:05 localhost lpmd[3242]: set cpufreq: 1, min: 800000, max: 2000000, conservative
Mar 3 13:39:06 localhost lpmd[3242]: get sensor "cpu0" value: 51.000000
Mar 3 13:39:06 localhost lpmd[3242]: get sensor "cpu1" value: 53.000000
Mar 3 13:39:06 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:39:06 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
Mar 3 13:39:07 localhost lpmd[3242]: get sensor "cpu0" value: 53.000000
Mar 3 13:39:07 localhost lpmd[3242]: get sensor "cpu1" value: 53.000000
Mar 3 13:39:07 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:39:07 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
Mar 3 13:39:08 localhost lpmd[3242]: get sensor "cpu0" value: 50.000000
Mar 3 13:39:08 localhost lpmd[3242]: get sensor "cpu1" value: 48.000000
Mar 3 13:39:08 localhost lpmd[3242]: cpufreq for cpu: 0 unchanged, therefore skip
Mar 3 13:39:08 localhost lpmd[3242]: cpufreq for cpu: 1 unchanged, therefore skip
не из под рута тоже работает, просто не сможет поменять cpufreq
Буду очень благодарен, если укажите на любые ошибки.
Ты уж прости, у меня сейчас на работе делов хватает. Разгребу немного, напишу.
Пока еще даже код не смотрел. Мне сейчас "программизма" wink на работе хватает.
Устаю уж больно сейчас.
Работаю на фабрике межкомнатных дверей. (как уже ясно программистом)
Пытаются начать вести учет по материалам. smile С учетом того, что его там никогда не было это просто что-то. :( oO
А еще у меня сын подрастает. 7 месяцев уже. Большой совсем. :D
Ходить пытается. smile
Так приятно смотреть, как мой сын ходит (за ручки пока).
Столько радости у него на лице. smile
Сам радуюсь и за сына рад.
Я счастливый отец. :D
Есть просьба, если несложно, и если имеется ноутбук или любое другое устройство работающее от батарейки с линуксом на борту, поместите здесь вывод этих команд:
Добавил тест батареи и переписал сенсоры, осталось добавить монитор процессов по именам, прикрутить getopt, добавить отправку сообщений в syslog из lua, и далее только доводка до кондиции.
Конфиг теперь выглядит так:
Показать
-- example configuration for Intel(R) Core(TM)2 Duo CPU T5800 @ 2.00GHz
require "math" --require "io"
-- -- global options --
options = {
poll_interval =1.1;-- 1.1 second
profile ="default"; -- mask that determines which messages will be send to the syslog
logmask = {"ERROR","WARNING","NOTICE","INFO","DEBUG"}; }
-- -- define sensors --
cpu0 =getSensor("temp1")-- sensor name in the system
cpu1 =getSensor("temp2")
-- -- fuzzy logic membership data for the sensors -- fuzzy(low false, low true, hi true, hi false) --
cpu_cold =fuzzy(-50, -50,24,42)
cpu_warm =fuzzy(24,42,48,66)
cpu_hot =fuzzy(48,66,140,140)
-- -- fuzzy logic membership data for the battery values in 0-100 range --
charged =fuzzy(20,80,100,100)
discharged =fuzzy(0,0,20,80)
-- -- policy data for the cpufreq --
low_policy =policy(800000,1600000,"conservative")
norm_policy =policy(800000,2000000,"conservative")
perf_policy =policy(800000,2000000,"ondemand")
-- -- base fuzzy logic operations --
fuzzy_and = math.min
fuzzy_or = math.max functionfuzzy_not(n)return1.0- n end functionvery(n)return n^2end functionnot_very(n)return n^0.5end functionnorm(n)if n >=0.5then return true else return false end end
profiles = {
default =function() -- -- fan control example -- --f = io.output(" put here path to the fan control ","w") --f:write(math.floor(255 * sensor("cpu", "hot"))) --f:flush() --f:close()
ifnorm(fuzzy_or(sensor(cpu0, cpu_hot),sensor(cpu1, cpu_hot),battery(discharged)))then --print("hot") if notcpufreq({0,1},low_policy)then --lpmdStopLoop() --return end elseifnorm(fuzzy_and(fuzzy_or(sensor(cpu0, cpu_warm),sensor(cpu1, cpu_warm)),battery(charged)))then --print("warm") if notcpufreq({0,1},norm_policy)then --lpmdStopLoop() --return end elseifnorm(fuzzy_and(sensor(cpu0, cpu_cold),sensor(cpu1, cpu_cold),battery(charged)))then --print("other") if notcpufreq({0,1},perf_policy)then --lpmdStopLoop() --return end end end, }
Имена батареи и адаптера заданы в коде, если у вас другие, правьте lpmd_psupply.c (надо было выкладывать вывод systool -c power_supply -v).
Кто не знает что такое нечёткая логика читайте на википедии.
Всё то же, что и в обычной логике, за исключением того, что результат - дробь в пределах от 0.0 до 1.0, где 1.0 - true, а 0.0 - false, промежуток на ваше усмотрение.
В конфиге функция norm делает из нечёткой логики обычную.
Функции sensor и battery возвращают нечёткие значения, функция onAc возвращает lua boolean.
Лучший, на мой взгляд, туториал по луа.
Добавил сканирование процессов на совпадение имени и ещё кое что интересное, смотрите в конфигурации . У меня
работает уже больше двух недель, скоро, думаю, бету оформлю, если ни кому не интересно, то функциональность расширять больше не планирую.
Это мой текущий конфиг:
Показать
-- example configuration for Intel(R) Core(TM)2 Duo CPU T5800 @ 2.00GHz
require "math" --require "io"
-- -- global options --
options = { -- -- Set poll interval between profile calling to 1.1 seconds. --
poll_interval =1.1, -- -- Set active profile. --
profile ="ProfileOnAC", -- -- Mask that determines which messages will be send to the syslog. --
logmask = {"ERROR","WARNING","NOTICE","INFO","DEBUG"} --logmask = { "ERROR", "WARNING", "NOTICE" } }
-- -- Define sensors. -- "temp1", "temp2" - sensor name in the system --
cpu0 =getSensor("temp1")
cpu1 =getSensor("temp2")
-- -- Fuzzy logic membership data for the sensors. -- fuzzy(low false, low true, hi true, hi false) --
cpu_cold =fuzzy(-50, -50,6,40)
cpu_warm =fuzzy(6,40,44,80)
cpu_hot =fuzzy(46,80,150,150)
-- -- Fuzzy logic membership data for the battery. -- Values in 0-100 range. --
charged =fuzzy(20,80,100,100)
discharged =fuzzy(0,0,20,80)
-- -- Define command names of processes for monitoring. --
video =comm("mplayer","vlc")
encode =comm("transcode","mencoder","lame","oggenc")
compr =comm("gzip","bzip2","lzma","xz","tar","mksquashfs")
build =comm("emerge","make","scons")
-- -- Define policy data for the cpufreq. -- Get available from cpufreq-info. --
min_policy =policy(800000,800000,"powersave")
low_policy =policy(800000,1600000,"conservative") --norm_policy = policy(800000,2000000,"conservative")
norm_policy =policy("800 MHz","2.00 GHz","conservative")
perf_policy =policy("800 MHz","2.00 GHz","ondemand")
max_policy =policy("1.2 GHz","2.0 GHz","ondemand")
-- -- Save policy for all cpus when lpmd start, to restore policy when lpmd exit. --
save_cpus = {} for i =1,sysCpus()do
save_cpus[i] =policy(cpufreq(i-1)) end
-- -- Define triggers. --
tAC =trigger("Rule on AC")
tBAT =trigger("Rule on BAT") --tProfile("Profile")
-- -- Base fuzzy logic operations. --
fuzzy_and = math.min
fuzzy_or = math.max functionfuzzy_not(n)return1.0- n end functionvery(n)return n^2end functionnot_very(n)return n^0.5end functionnorm(n)if n >=0.5then return true else return false end end
-- -- Sensor emulation to debug configuration. --
fake_sen_v =20-- start value
fake_sen_d =0.3-- delta per second
fake_sen_max =80-- max value
fake_sen_min = -10-- min value
fake_sen_c =lpmdCycle() -1
functionfake_temp(unused, fuzzy_p) if fake_sen_c ~=lpmdCycle()then local k = math.abs(fake_sen_d) *lpmdPoll() if fake_sen_v > (fake_sen_max - k)then
fake_sen_d = -math.abs(fake_sen_d) elseif fake_sen_v < (fake_sen_min + k)then
fake_sen_d = math.abs(fake_sen_d) end
fake_sen_v = fake_sen_v + (fake_sen_d *lpmdPoll())
fake_sen_c =lpmdCycle() end print(fake_sen_v) log("DEBUG",string.format("fake temp=%3.1f", fake_sen_v))
returnfuzzy_p(fake_sen_v) end
--sens = fake_temp
sens = sensor
-- -- List of profile function. -- Active profile will be called in each poll. --
profiles = {
ProfileOnAC =function() local cpu01_hot =fuzzy_or(sens(cpu0, cpu_hot),sens(cpu1, cpu_hot)) -- -- Use trigger to run something in the first call. -- -- if tProfile(1) then -- end
-- -- Fan control example. -- -- f = io.output(" put here path to the fan control ") -- f:write(math.floor(255 * cpu01_hot)) -- f:flush() -- f:close()
ifnorm(very(cpu01_hot))then iftAC(1)then -- -- Set cpufreq to min_policy for all cpus. -- if notcpufreq("ALL", min_policy)then -- -- Stop profile calling if set policy is failed. -- lpmdLoop(false) end -- -- Change interval between profile calling to 5 seconds. -- lpmdPoll(5.0) end elseifnorm(fuzzy_not(cpu01_hot))andprocess(build,encode)then iftAC(2)then if notcpufreq("ALL", max_policy)then lpmdLoop(false) end lpmdPoll(2.0) end elseifprocess(build,encode,compr,video)then iftAC(3)then if notcpufreq("ALL", perf_policy)then lpmdLoop(false) end lpmdPoll(2.0) end else iftAC(4)then if notcpufreq("ALL", norm_policy)then lpmdLoop(false) end -- -- Restore interval between profile calling to default. -- lpmdPoll(options.poll_interval) end
end
-- -- Will be run if rule is changed. -- iftAC()then --print(tAC) -- Use to debug configuration. log("NOTICE",tostring(tAC)) for i =0,sysCpus() -1do log("NOTICE",string.format("current policy on cpu%d: min=%d, max=%d, %s", i,cpufreq(i))) end log("NOTICE",tostring(cpu0)) end
-- -- Switch to battery profile. -- if not onAc then lpmdProfile("ProfileOnBAT") lpmdPoll(3.0) end end,
ProfileOnBAT =function()
--if tProfile(2) then --end
local cpu01_hot =fuzzy_or(sens(cpu0, cpu_hot),sens(cpu1, cpu_hot))
ifnorm(very(cpu01_hot))then iftBAT(1)then if notcpufreq("ALL", min_policy)then lpmdLoop(false) end lpmdPoll(5.0) end elseifnorm(fuzzy_or(cpu01_hot,battery(discharged)))then iftBAT(2)then if notcpufreq("ALL", low_policy)then lpmdLoop(false) end lpmdPoll(4.0) end elseifbattery(charged)andprocess(compr,video)then iftBAT(3)then if notcpufreq("ALL", perf_policy)then lpmdLoop(false) end lpmdPoll(2.0) end else iftBAT(4)then if notcpufreq("ALL", norm_policy)then lpmdLoop(false) end lpmdPoll(3.0) end end
iftBAT()then log("NOTICE",tostring(tBAT)) for i =0,sysCpus() -1do log("NOTICE",string.format("current policy on cpu%d: min=%d, max=%d, %s", i,cpufreq(i))) end log("NOTICE",tostring(cpu0)) end
if onAc then lpmdProfile("ProfileOnAC") lpmdPoll(options.poll_interval) end end }
-- -- Finally function to restore something. -- Will be called once before exit. --
finally =function()
-- -- Restore cpufreq policy. -- log("INFO","call finally") if not onAc andnorm(battery(discharged))then cpufreq("ALL", low_policy) log("INFO",string.format("restore policy on all cpus: %s",tostring(low_policy))) else for i,pol inipairs(save_cpus)do cpufreq(i -1, pol) log("INFO",string.format("restore policy on cpu%i: %s", i-1,tostring(pol))) end end -- -- Get the currently used cpufreq policy for all cpus -- and send them to the syslog. -- for i =0,sysCpus() -1do log("WARNING",string.format("current policy on cpu%d: min=%d, max=%d, %s", i,cpufreq(i))) end log("WARNING","lpmd exit") end
-- vim:ts=4:ft=lua:fdm=marker
Удивительно, но несмотря на lua, обгоняет cpufreqd, запущенный с эквивалентной конфигурацией, практически по всем параметрам.
ps -C lpmd,cpufreqd -o vsize,rssize,size,pcpu,cputime,comm
checkconfig() {
if [ ! -e /etc/lpmd.lua ] ; then
eerror "You need an /etc/lpmd.lua file first."
return 1
fi
}
start() {
checkconfig || return 1
ebegin "Starting lpmd"
for CPU in $(cpufreq-info -r); do
chown "${USER}:root" /sys/devices/system/cpu/cpu${CPU}/cpufreq/scaling_governor
chown "${USER}:root" /sys/devices/system/cpu/cpu${CPU}/cpufreq/scaling_max_freq
chown "${USER}:root" /sys/devices/system/cpu/cpu${CPU}/cpufreq/scaling_min_freq
done
start-stop-daemon -u ${USER} -b -m -p /var/run/lpmd.pid \
--start --exec /usr/sbin/lpmd
eend $?
}
stop() {
ebegin "Stopping lpmd"
for CPU in $(cpufreq-info -r); do
chown 'root:root' /sys/devices/system/cpu/cpu${CPU}/cpufreq/scaling_governor
chown 'root:root' /sys/devices/system/cpu/cpu${CPU}/cpufreq/scaling_max_freq
chown 'root:root' /sys/devices/system/cpu/cpu${CPU}/cpufreq/scaling_min_freq
done
start-stop-daemon --stop --pidfile /var/run/lpmd.pid
eend $?
}
Для тех, кто захочет прпробовать, но не хочет запускать из под рута добавил запуск от любого пользователя, вроде работает.
Ещё могу предложить настройки для syslog-ng.
Показать
text
filter f_lpmd_all { facility(daemon) and program("^lpmd$") and level(debug..crit); };
filter f_lpmd { facility(daemon) and program("^lpmd$") and level(notice..crit); };
filter f_not_lpmd { not program("^lpmd$"); }
Добавил cpu-usage и обработчик Lua panic, выложил tar, сборка тривиальна - make CFLAGS="ваши флаги для компилятора", можно просто make.
Зависимости:
lua-5.1.4
lm_sensors-3
sysfsutils
cpufrequtils
На ближайшее время активное развитие заброшу, ибо надоело, только почищу, ну и найденные ошибки исправлять буду.
Хочу еще написать на Lua модуль для манипуляции cpu vid подробности читайте здесь.
У меня на Core2 T5800 даёт феноменальный результат, при длительной компиляции температура не поднимается выше 60C, при этом вентилятор еле дует, если cpu vid имеет стандартые значения, то температура может доходить до 70C, и вентилятор дует во всю, представьте как это может влиять на время работы на батарее.
Пробный вариант у меня уже есть.
В конфигурации ошибочка была у вызовов функции onAc отсутствовали скобки, из за этого вместо результата функции использовалась сама функция, и результат был всегда true.
Я батареей редко пользуюсь, поэтому внимания не обращал.
результат будет такой же, без заметных потерь в производительности.
В принципе сканировать можно что угодно из того, что имеется в /proc/[pid]/*, просто придумать применение не смог, поэтому возможность порезал.
Жду жалоб и предложений, иначе заброшу.
On Fri, May 06, 2011 at 10:25:08AM -0400, Robert P. J. Day wrote:
> and i want to more emphasize kobjects and sysfs. to that end, i'm
> aware of the "sysfsutils" package, although i haven't used it yet.
It's obsolete, and doesn't work on modern kernels, please never use it.
Use libudev instead if you want access to sysfs data for devices.
On Fri, May 06, 2011 at 10:25:08AM -0400, Robert P. J. Day wrote:
> and i want to more emphasize kobjects and sysfs. to that end, i'm
> aware of the "sysfsutils" package, although i haven't used it yet.
It's obsolete, and doesn't work on modern kernels, please never use it.
Use libudev instead if you want access to sysfs data for devices.
thanks,
greg k-h
[/quote]
Я смотрел udev, там просто перечисление устройств в сыром виде, как просмотреть class я не нашёл, и никакой документации.
sysfsutils предоставляют удобную либу для обзора sysfs в разных вариантах, и хорошо документировано.
И что, я должен сам писать энумератор для sysfs?
К тому-же cpufreqd тоже использует sysfsutils, и думаю не только он.
Мало ли чего кто-то там написал.
Что sysfsutils не работает на современных ядрах - бред сивой кобылы.