/usr/bin/likwid-powermeter is in likwid 4.3.1+dfsg1-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | #!/usr/bin/lua5.2
--[[
* =======================================================================================
*
* Filename: likwid-powermeter.lua
*
* Description: An application to get information about power
* consumption on architectures implementing the RAPL interface.
*
* Version: 4.3.1
* Released: 04.01.2018
*
* Author: Thomas Roehl (tr), thomas.roehl@gmail.com
* Project: likwid
*
* Copyright (C) 2018 RRZE, University Erlangen-Nuremberg
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* =======================================================================================
]]
package.path = '/usr/share/lua/?.lua;' .. package.path
local likwid = require("likwid")
print_stdout = print
print_stderr = function(...) for k,v in pairs({...}) do io.stderr:write(v .. "\n") end end
local function version()
print_stdout(string.format("likwid-powermeter -- Version %d.%d.%d (commit: %s)",likwid.version,likwid.release,likwid.minor,likwid.commit))
end
local function examples()
print_stdout("Examples:")
print_stdout("Measure the power consumption for 4 seconds on socket 1")
print_stdout("likwid-powermeter -s 4 -c 1")
print_stdout("")
print_stdout("Use it as wrapper for an application to measure the energy for the whole execution")
print_stdout("likwid-powermeter -c 1 ./a.out")
end
local function usage()
version()
print_stdout("A tool to print power and clocking information on x86 CPUs.\n")
print_stdout("Options:")
print_stdout("-h, --help\t Help message")
print_stdout("-v, --version\t Version information")
print_stdout("-V, --verbose <level>\t Verbose output, 0 (only errors), 1 (info), 2 (details), 3 (developer)")
print_stdout("-M <0|1>\t\t Set how MSR registers are accessed, 0=direct, 1=accessDaemon")
print_stdout("-c <list>\t\t Specify sockets to measure")
print_stdout("-i, --info\t Print information from MSR_PKG_POWER_INFO register and Turbo mode")
print_stdout("-s <duration>\t Set measure duration in us, ms or s. (default 2s)")
print_stdout("-p\t\t Print dynamic clocking and CPI values, uses likwid-perfctr")
print_stdout("-t\t\t Print current temperatures of all CPU cores")
print_stdout("-f\t\t Print current temperatures in Fahrenheit")
print_stdout("")
examples()
end
local config = likwid.getConfiguration();
print_info = false
use_perfctr = false
stethoscope = false
fahrenheit = false
print_temp = false
verbose = 0
if config["daemonMode"] < 0 then
access_mode = 1
else
access_mode = config["daemonMode"]
end
time_interval = 2.E06
time_orig = "2s"
read_interval = 30.E06
sockets = {}
domainList = {"PKG", "PP0", "PP1", "DRAM", "PLATFORM"}
cpuinfo = likwid.getCpuInfo()
cputopo = likwid.getCpuTopology()
numatopo = likwid.getNumaInfo()
affinity = likwid_getAffinityInfo()
for opt,arg in likwid.getopt(arg, {"V:", "c:", "h", "i", "M:", "p", "s:", "v", "f", "t", "help", "info", "version", "verbose:"}) do
if (type(arg) == "string") then
local s,e = arg:find("-");
if s == 1 then
print_stderr(string.format("Argmument %s to option -%s starts with invalid character -.", arg, opt))
print_stderr("Did you forget an argument to an option?")
os.exit(1)
end
end
if opt == "h" or opt == "help" then
usage()
os.exit(0)
elseif opt == "v" or opt == "version" then
version()
os.exit(0)
elseif (opt == "c") then
num_sockets, sockets = likwid.sockstr_to_socklist(arg)
if num_sockets == 0 then
os.exit(1)
end
elseif (opt == "M") then
access_mode = tonumber(arg)
if (access_mode == nil) then
print_stderr("Access mode (-M) must be an number")
usage()
os.exit(1)
elseif (access_mode < 0) or (access_mode > 1) then
print_stderr(string.format("Access mode (-M) %d not valid.",access_mode))
usage()
os.exit(1)
end
elseif opt == "i" or opt == "info" then
print_info = true
elseif (opt == "p") then
use_perfctr = true
elseif (opt == "f") then
fahrenheit = true
print_temp = true
elseif (opt == "t") then
print_temp = true
elseif opt == "V" or opt == "verbose" then
verbose = tonumber(arg)
likwid.setVerbosity(verbose)
elseif (opt == "s") then
time_interval = likwid.parse_time(arg)
time_orig = arg
stethoscope = true
elseif opt == "?" then
print_stderr("Invalid commandline option -"..arg)
os.exit(1)
elseif opt == "!" then
print_stderr("Option requires an argument")
os.exit(1)
end
end
cpulist = {}
before = {}
after = {}
if #sockets > 0 then
for i,socketId in pairs(sockets) do
local affinityID = "S"..tostring(socketId)
for j, domain in pairs(affinity["domains"]) do
if domain["tag"] == affinityID then
table.insert(cpulist,domain["processorList"][1])
before[domain["processorList"][1]] = {}
after[domain["processorList"][1]] = {}
for _, id in pairs(domainList) do
before[domain["processorList"][1]][id] = 0
after[domain["processorList"][1]][id] = 0
end
end
end
end
else
for j, domain in pairs(affinity["domains"]) do
if domain["tag"]:match("S%d+") then
table.insert(cpulist,domain["processorList"][1])
table.insert(sockets, domain["tag"]:match("S(%d+)"))
before[domain["processorList"][1]] = {}
after[domain["processorList"][1]] = {}
for _, id in pairs(domainList) do
before[domain["processorList"][1]][id] = 0
after[domain["processorList"][1]][id] = 0
end
end
end
end
if likwid.setAccessClientMode(access_mode) ~= 0 then
os.exit(1)
end
power = likwid.getPowerInfo()
if not power then
print_stderr(string.format("The %s does not support reading power data",cpuinfo["name"]))
os.exit(1)
end
if not use_perfctr then
print_stdout(likwid.hline);
print_stdout(string.format("CPU name:\t%s",cpuinfo["osname"]))
print_stdout(string.format("CPU type:\t%s",cpuinfo["name"]))
if cpuinfo["clock"] > 0 then
print_stdout(string.format("CPU clock:\t%3.2f GHz",cpuinfo["clock"] * 1.E-09))
else
print_stdout(string.format("CPU clock:\t%3.2f GHz",likwid.getCpuClock() * 1.E-09))
end
print_stdout(likwid.hline)
end
if print_info or verbose > 0 then
if (power["turbo"]["numSteps"] > 0) then
print_stdout(string.format("Base clock:\t%.2f MHz", power["baseFrequency"]))
print_stdout(string.format("Minimal clock:\t%.2f MHz", power["minFrequency"]))
print_stdout("Turbo Boost Steps:")
for i,step in pairs(power["turbo"]["steps"]) do
print_stdout(string.format("C%d %.2f MHz",i-1,power["turbo"]["steps"][i]))
end
end
print_stdout(likwid.hline)
end
if power["hasRAPL"] == 0 then
print_stderr("Measuring power is not supported on this machine")
os.exit(1)
end
if (print_info) then
for i, dname in pairs(domainList) do
local domain = power["domains"][dname]
if domain and domain["supportInfo"] then
print_stdout(string.format("Info for RAPL domain %s:", dname));
print_stdout(string.format("Thermal Spec Power: %g Watt",domain["tdp"]*1E-6))
print_stdout(string.format("Minimum Power: %g Watt",domain["minPower"]*1E-6))
print_stdout(string.format("Maximum Power: %g Watt",domain["maxPower"]*1E-6))
print_stdout(string.format("Maximum Time Window: %g micro sec",domain["maxTimeWindow"]))
print_stdout()
end
end
if power["minUncoreFreq"] > 0 and power["maxUncoreFreq"] > 0 then
print_stdout("Info about Uncore:")
print_stdout(string.format("Minimal Uncore frequency: %g MHz", power["minUncoreFreq"]))
print_stdout(string.format("Maximal Uncore frequency: %g MHz", power["maxUncoreFreq"]))
print_stdout()
end
if power["perfBias"] then
print_stdout(string.format("Performance energy bias: %.0f (0=highest performance, 15 = lowest energy)", power["perfBias"]))
print_stdout()
end
print_stdout(likwid.hline)
end
if (stethoscope) and (time_interval < power["timeUnit"]) then
print_stderr("Time interval too short, minimum measurement time is "..tostring(power["timeUnit"]).. " us")
os.exit(1)
end
local execString = ""
if use_perfctr then
affinity = likwid.getAffinityInfo()
argString = ""
for i,socket in pairs(sockets) do
argString = argString .. string.format("S%u:0-%u",socket,(cputopo["numCoresPerSocket"]*cputopo["numThreadsPerCore"])-1)
if (i < #sockets) then
argString = argString .. "@"
end
end
execString = string.format("/usr/bin/likwid-perfctr -C %s -f -g CLOCK ",argString)
end
local execList = {}
if #arg == 0 then
if use_perfctr then
execString = execString .. string.format(" -S %s ", time_orig)
stethoscope = false
else
stethoscope = true
end
else
for i=1, likwid.tablelength(arg)-2 do
table.insert(execList, arg[i])
end
if use_perfctr then
execString = execString .. table.concat(execList," ")
else
execString = table.concat(execList," ")
end
end
local exitvalue = 0
if not print_info and not print_temp then
if stethoscope or (#arg > 0 and not use_perfctr) then
for i,socket in pairs(sockets) do
cpu = cpulist[i]
for idx, dom in pairs(domainList) do
if (power["domains"][dom]["supportStatus"]) then before[cpu][dom] = likwid.startPower(cpu, idx) end
end
end
time_before = likwid.startClock()
if stethoscope then
if read_interval < time_interval then
while ((read_interval <= time_interval) and (time_interval > 0)) do
likwid.sleep(read_interval)
for i,socket in pairs(sockets) do
cpu = cpulist[i]
for idx, dom in pairs(domainList) do
if (power["domains"][dom]["supportStatus"]) then after[cpu][dom] = likwid.stopPower(cpu, idx) end
end
end
time_interval = time_interval - read_interval
if time_interval < read_interval then
read_interval = time_interval
end
end
else
likwid.sleep(time_interval)
end
else
local pid = likwid.startProgram(table.concat(execList," "), 0, {})
if not pid then
print_stderr(string.format("Failed to execute %s!",table.concat(execList," ")))
likwid.finalize()
os.exit(1)
end
while true do
if likwid.getSignalState() ~= 0 then
likwid.killProgram()
break
end
local remain = likwid.sleep(read_interval)
for i,socket in pairs(sockets) do
cpu = cpulist[i]
for idx, dom in pairs(domainList) do
if (power["domains"][dom]["supportStatus"]) then after[cpu][dom] = likwid.stopPower(cpu, idx) end
end
end
exitvalue = likwid.checkProgram(pid)
if remain > 0 or exitvalue >= 0 then
io.stdout:flush()
break
end
end
end
time_after = likwid.stopClock()
for i,socket in pairs(sockets) do
cpu = cpulist[i]
for idx, dom in pairs(domainList) do
if (power["domains"][dom]["supportStatus"]) then after[cpu][dom] = likwid.stopPower(cpu, idx) end
end
end
runtime = likwid.getClock(time_before, time_after)
print_stdout(likwid.hline)
print_stdout(string.format("Runtime: %g s",runtime))
for i,socket in pairs(sockets) do
cpu = cpulist[i]
print_stdout(string.format("Measure for socket %d on CPU %d", socket,cpu ))
for j, dom in pairs(domainList) do
if power["domains"][dom]["supportStatus"] then
local energy = likwid.calcPower(before[cpu][dom], after[cpu][dom], j-1)
print_stdout(string.format("Domain %s:", dom))
print_stdout(string.format("Energy consumed: %g Joules",energy))
print_stdout(string.format("Power consumed: %g Watt",energy/runtime))
end
end
if i < #sockets then print_stdout("") end
end
print_stdout(likwid.hline)
else
err = os.execute(execString)
if err == false then
print_stderr(string.format("Failed to execute %s!", execString))
likwid.putPowerInfo()
likwid.finalize()
os.exit(1)
end
end
end
if print_temp and (string.find(cpuinfo["features"],"TM2") ~= nil) then
print_stdout(likwid.hline)
print_stdout("Current core temperatures:");
for i=1,cputopo["numSockets"] do
local tag = "S" .. tostring(i-1)
for _, domain in pairs(affinity["domains"]) do
if domain["tag"] == tag then
for j=1,#domain["processorList"] do
local cpuid = domain["processorList"][j]
likwid.initTemp(cpuid);
if (fahrenheit) then
local f = 1.8*tonumber(likwid.readTemp(cpuid))+32
print_stdout(string.format("Socket %d Core %d: %.0f F",i-1,cpuid, f));
else
print_stdout(string.format("Socket %d Core %d: %.0f C",i-1,cpuid, tonumber(likwid.readTemp(cpuid))));
end
end
end
end
end
print_stdout(likwid.hline)
end
likwid.putPowerInfo()
likwid.finalize()
os.exit(exitvalue)
|