diff --git a/src/applications/likwid-sysfeatures.lua b/src/applications/likwid-sysfeatures.lua index 87bada0f1..ff426d922 100644 --- a/src/applications/likwid-sysfeatures.lua +++ b/src/applications/likwid-sysfeatures.lua @@ -61,6 +61,8 @@ local function usage() print_stdout("-s, --set \t Set feature(s) to the given value") print_stdout(" \t format: .= or just = if unique") print_stdout(" \t can be a comma-separated list of features") + print_stdout(" --saveall \t Save all available rw-features to file") + print_stdout(" --loadall \t Load all features from file") print_stdout("-O\t\t\t Output results in CSV") print_stdout("-V, --verbose \t Set verbosity\n") end @@ -121,7 +123,7 @@ local verbose = 0 local output_csv = false -- parse the command line -for opt,arg in likwid.getopt(arg, {"h","v","l","p","d:","g:","s:","a", "O","help","version","list", "print", "set:", "get:","all", "cpus:", "V:", "verbose:"}) do +for opt,arg in likwid.getopt(arg, {"h","v","l","p","d:","g:","s:","a", "O","help","version","list", "print", "set:", "get:","all", "cpus:", "V:", "verbose:", "saveall:", "loadall:"}) do if (type(arg) == "string") then local s,e = arg:find("-"); if s == 1 then @@ -152,6 +154,10 @@ for opt,arg in likwid.getopt(arg, {"h","v","l","p","d:","g:","s:","a", "O","help getList = likwid.stringsplit(arg, ",") elseif opt == "s" or opt == "set" then setList = likwid.stringsplit(arg, ",") + elseif opt == "saveall" then + saveFeatures = arg + elseif opt == "loadall" then + loadFeatures = arg elseif opt == "?" then print_stderr("Invalid commandline option -"..arg) os.exit(1) @@ -163,12 +169,12 @@ end -- validate command line input -if (not printDevices) and (not listFeatures) and (not allFeatures) and (#getList == 0) and (#setList == 0) then +if (not printDevices) and (not listFeatures) and (not allFeatures) and (not saveFeatures) and (not loadFeatures) and (#getList == 0) and (#setList == 0) then print_stderr("No operations specified, exiting...") os.exit(1) end -if (printDevices or listFeatures or allFeatures) and (#getList > 0 or #setList > 0) then - print_stderr("Cannot list features and get/set at the same time") +if (printDevices or listFeatures or allFeatures or saveFeatures or loadFeatures) and (#getList > 0 or #setList > 0) then + print_stderr("Cannot list features and get/set/load/save at the same time") os.exit(1) end if #devList == 0 then @@ -200,20 +206,21 @@ end local ft_list = likwid.sysFeatures_list() -- print available devices +device_types = {} +device_types[likwid.hwthread] = "HWThread (T)" +device_types[likwid.core] = "Core (C)" +device_types[likwid.numa] = "NUMA (M)" +device_types[likwid.die] = "Die (D)" +device_types[likwid.socket] = "Socket (S)" +device_types[likwid.node] = "Node (N)" +if likwid.nvSupported() then + device_types[likwid.nvidia_gpu] = "Nvidia GPU (GN)" +end +if likwid.rocmSupported() then + device_types[likwid.amd_gpu] = "AMD GPU (GA)" +end + if printDevices then - device_types = {} - device_types[likwid.hwthread] = "HWThread (T)" - device_types[likwid.core] = "Core (C)" - device_types[likwid.numa] = "NUMA (M)" - device_types[likwid.die] = "Die (D)" - device_types[likwid.socket] = "Socket (S)" - device_types[likwid.node] = "Node (N)" - if likwid.nvSupported() then - device_types[likwid.nvidia_gpu] = "Nvidia GPU (GN)" - end - if likwid.rocmSupported() then - device_types[likwid.amd_gpu] = "AMD GPU (GA)" - end for devtype, name in pairs(device_types) do print(string.format("%s:", name)) devices = likwid.getAvailableDevices(devtype) @@ -384,5 +391,88 @@ if #setList > 0 and #devList > 0 then os.exit(0) end +-- save all read/write features to file +if saveFeatures then + local file = io.open(saveFeatures, "w") + -- iterate over all device types + for devtype, _ in pairs(device_types) do + -- iterate over all features + for _,f in pairs(ft_list) do + local full_name = string.format("%s.%s", f.Category, f.Name) + -- only allow matching device types and if feature is readable and writable + if f.TypeID ~= devtype or f.ReadOnly or f.WriteOnly then + goto next_feat + end + + -- actually read the features + for _, dev in pairs(likwid.getAllDevices(devtype)) do + local lw_dev = likwid.createDevice(devtype, dev) + local v, err = likwid.sysFeatures_get(full_name, lw_dev) + if err then + print_stderr(string.format("Failed to get feature '%s' on device %s:%d: %s", full_name, lw_dev:typeName(), lw_dev:id(), err)) + goto next_feat + end + file:write(string.format("%s.%s@%s=%s\n", f.Category, f.Name, lw_dev:id(), v)) + end + + ::next_feat:: + end + end + + file:close() + + likwid.finalizeSysFeatures() + os.exit(0) +end + +-- load all features from file +if loadFeatures then + for line in io.lines(loadFeatures) do + -- split string like the following: cpu_freq.governor@5=schedutil + local part1 = likwid.stringsplit(line, "=") + if #part1 ~= 2 then + print_stderr("Invalid line: " .. line) + os.exit(1) + end + local part2 = likwid.stringsplit(part1[1], "@") + if #part2 ~= 2 then + print_stderr("Invalid line: " .. line) + os.exit(1) + end + part3 = likwid.stringsplit(part2[1], ".") + if #part3 ~= 2 then + print_stderr("Invalid line: " .. line) + os.exit(1) + end + local feat_cat = part3[1] + local feat_name = part3[2] + local dev_id = part2[2] + local value = part1[2] + + local full_name = string.format("%s.%s", feat_cat, feat_name) + + -- get device type of this particular feature + local devtype = nil + for _, f in pairs(ft_list) do + if f.Name == feat_name and f.Category == feat_cat then + devtype = f.TypeID + break + end + end + if not devtype then + print_stderr(string.format("Unknown feature: '%s'", full_name)) + os.exit(1) + end + local lw_dev = likwid.createDevice(devtype, dev_id) + local success, err = likwid.sysFeatures_set(full_name, lw_dev, value) + if not success then + print_stderr(string.format("Failed to set feature '%s' on device %s:%d to %s: %s", full_name, lw_dev:typeName(), lw_dev:id(), value, err)) + end + end + + likwid.finalizeSysFeatures() + os.exit(0) +end + likwid.finalizeSysFeatures() os.exit(0) diff --git a/src/applications/likwid.lua b/src/applications/likwid.lua index b777646ca..db6dd6aaf 100644 --- a/src/applications/likwid.lua +++ b/src/applications/likwid.lua @@ -189,6 +189,7 @@ likwid.finalizeSysFeatures = likwid_finalizeSysFeatures likwid.createDevice = likwid_createDevice likwid.createDevicesFromString = likwid_createDevicesFromString likwid.getAvailableDevices = likwid_getAvailableDevices +likwid.getAllDevices = likwid_getAllDevices likwid.getCudaTopology = likwid_getCudaTopology likwid.putCudaTopology = likwid_putCudaTopology diff --git a/src/luawid.c b/src/luawid.c index 58d28a1f5..73f1a3a5a 100644 --- a/src/luawid.c +++ b/src/luawid.c @@ -3828,14 +3828,24 @@ static int lua_likwid_destroyDevice(lua_State *L) return 0; } -static int lua_likwid_getAvailableDevices(lua_State *L) +static int lua_likwid_getDevices(lua_State *L, bool all) { const LikwidDeviceType type = luaL_checknumber(L, 1); char **id_list = NULL; size_t id_list_len = 0; - int err = likwid_device_get_available(type, &id_list, &id_list_len); - if (err < 0) - luaL_error(L, "likwid_device_get_available failed: %s", strerror(-err)); + int err; + if (all) + { + err = likwid_device_get_all(type, &id_list, &id_list_len); + if (err < 0) + luaL_error(L, "likwid_device_get_all failed: %s", strerror(-err)); + } + else + { + err = likwid_device_get_available(type, &id_list, &id_list_len); + if (err < 0) + luaL_error(L, "likwid_device_get_available failed: %s", strerror(-err)); + } lua_newtable(L); @@ -3850,6 +3860,16 @@ static int lua_likwid_getAvailableDevices(lua_State *L) return 1; } +static int lua_likwid_getAvailableDevices(lua_State *L) +{ + return lua_likwid_getDevices(L, false); +} + +static int lua_likwid_getAllDevices(lua_State *L) +{ + return lua_likwid_getDevices(L, true); +} + static int lua_likwiddevice_get_typeId(lua_State *L) { const LikwidDevice_t dev = *(LikwidDevice_t *)luaL_checkudata(L, 1, "LikwidDevice_t"); @@ -4249,6 +4269,7 @@ int __attribute__((visibility("default"))) luaopen_liblikwid(lua_State *L) { lua_register(L, "likwid_createDevicesFromString",lua_likwid_createDevicesFromString); lua_register(L, "likwid_createDevice",lua_likwid_createDevice); lua_register(L, "likwid_getAvailableDevices",lua_likwid_getAvailableDevices); + lua_register(L, "likwid_getAllDevices",lua_likwid_getAllDevices); #endif /* LIKWID_WITH_SYSFEATURES */ #ifdef __MIC__ setuid(0);