From 480f195dde7ef1fd9fd81ce0ea18924d81a4eda9 Mon Sep 17 00:00:00 2001 From: Mavridis Philippe Date: Mon, 30 Sep 2024 23:58:12 +0300 Subject: Superkaramba: add GPU load sensor The sensor has a required `driver` parameter and an optional `gpu` parameter. - The former specifies the backend to use to query the system about GPU load. - The latter specifies the id of the GPU to check. If left out, the backend default will be used. For now it only supports NVidia GPUs via the `nvidia` driver, but it can be extended. Signed-off-by: Mavridis Philippe --- superkaramba/src/CMakeLists.txt | 4 +- superkaramba/src/gpusensor.cpp | 129 ++++++++++++++++++++++++++++++++++++++++ superkaramba/src/gpusensor.h | 52 ++++++++++++++++ superkaramba/src/karamba.cpp | 20 +++++++ superkaramba/src/karamba.h | 7 ++- 5 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 superkaramba/src/gpusensor.cpp create mode 100644 superkaramba/src/gpusensor.h (limited to 'superkaramba/src') diff --git a/superkaramba/src/CMakeLists.txt b/superkaramba/src/CMakeLists.txt index 211ee0c..c38d41b 100644 --- a/superkaramba/src/CMakeLists.txt +++ b/superkaramba/src/CMakeLists.txt @@ -53,8 +53,8 @@ tde_add_executable( superkaramba AUTOMOC sknewstuff.h sknewstuff.cpp superkarambasettings.kcfgc themelocale.cpp input.cpp sklineedit.cpp input_python.cpp - svcgrp_python.cpp - LINK tdeio-shared ${PYTHON_LIBRARIES} + svcgrp_python.cpp gpusensor.cpp + LINK tdeio-shared ${PYTHON_LIBRARIES} ${TDENEWSTUFF_LIBRARIES} ${LIBKVM_LIBRARIES} DESTINATION ${BIN_INSTALL_DIR} diff --git a/superkaramba/src/gpusensor.cpp b/superkaramba/src/gpusensor.cpp new file mode 100644 index 0000000..d95de59 --- /dev/null +++ b/superkaramba/src/gpusensor.cpp @@ -0,0 +1,129 @@ +/******************************************************************************* + GPU sensor + Copyright (C) 2024 Mavridis Philippe + + 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 . + + Improvements and feedback are welcome! +*******************************************************************************/ + +// TQt +#include + +// TDE +#include +#include + +// Superkaramba +#include "gpusensor.h" + +GPUSensor::GPUSensor(TQString gpuDriver, TQString gpuId, int interval) + : Sensor(interval), m_gpuDriver(gpuDriver), m_gpuId(gpuId) +{ + if (m_gpuDriver.lower() == "nvidia") + { + TQString nvsmi = TDEStandardDirs::findExe("nvidia-smi"); + if (nvsmi.isNull()) + { + kdError() << "The NVidia System Management Interface software is not avaiable." << endl; + return; + } + + m_command << nvsmi << "--query-gpu" << "utilization.gpu" + << "--format=csv,noheader"; + + if (!m_gpuId.isNull()) + { + m_command << TQString("--id=%1").arg(m_gpuId); + } + } + + else + { + kdError() << "Unsupported driver specified for GPU sensor (" << m_gpuDriver << ");" << endl + << "\tSupported drivers are: nvidia" << endl; + } + + connect(&m_proc, TQ_SIGNAL(receivedStdout(TDEProcess*, char*, int)), + this, TQ_SLOT(receivedStdout(TDEProcess*, char*, int))); + connect(&m_proc, TQ_SIGNAL(processExited(TDEProcess*)), + this, TQ_SLOT(processExited(TDEProcess*))); +} + +GPUSensor::~GPUSensor() +{ +} + +void GPUSensor::update() +{ + if (m_command.isEmpty()) return; + + m_proc.clearArguments(); + m_proc << m_command; + + m_proc.start(TDEProcess::NotifyOnExit, TDEProcess::Stdout); +} + +void GPUSensor::receivedStdout(TDEProcess *proc, char *buffer, int buflen) +{ + buffer[buflen] = 0; + m_buffer += TQCString(buffer); +} + +TQString GPUSensor::getLoad() +{ + if (m_gpuDriver.lower() == "nvidia") + { + return m_buffer.left(m_buffer.length() - 3); + } + + return TQString::null; +} + +#define SUB_FORMAT_STR(fstring, value) \ + format.replace(TQRegExp(#fstring, false), value) +void GPUSensor::processExited(TDEProcess *proc) +{ + SensorParams *sp; + Meter *meter; + TQString format; + TQString load = getLoad(); + m_buffer = TQString::null; + + TQObjectListIt it(*objList); + while (it != 0) + { + sp = (SensorParams*)(*it); + meter = sp->getMeter(); + format = sp->getParam("FORMAT"); + + if( format.length() == 0) + { + format = "%v"; + } + + SUB_FORMAT_STR(%load, load); + SUB_FORMAT_STR(%v, load); + + meter->setValue(format); + ++it; + } +} + +#undef SUB_FORMAT_STR + +void GPUSensor::setMaxValue(SensorParams *sp) +{ + sp->getMeter()->setMax(100); +} + +#include "gpusensor.moc" \ No newline at end of file diff --git a/superkaramba/src/gpusensor.h b/superkaramba/src/gpusensor.h new file mode 100644 index 0000000..178e52e --- /dev/null +++ b/superkaramba/src/gpusensor.h @@ -0,0 +1,52 @@ +/******************************************************************************* + GPU sensor + Copyright (C) 2024 Mavridis Philippe + + 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 . + + Improvements and feedback are welcome! +*******************************************************************************/ + +#ifndef GPUSENSOR_H +#define GPUSENSOR_H + +// TDE +#include + +// Superkaramba +#include "sensor.h" + +class GPUSensor : public Sensor +{ + TQ_OBJECT + + public: + GPUSensor(TQString driver, TQString gpuId, int interval = 1000); + ~GPUSensor(); + + void update(); + void setMaxValue(SensorParams *sp); + + protected: + TQString getLoad(); + + private: + TQString m_gpuDriver, m_gpuId, m_buffer; + TQStringList m_command; + TDEProcess m_proc; + + public slots: + void receivedStdout(TDEProcess *proc, char *buffer, int buflen); + void processExited(TDEProcess *proc); +}; + +#endif // GPUSENSOR_H \ No newline at end of file diff --git a/superkaramba/src/karamba.cpp b/superkaramba/src/karamba.cpp index d4a74f7..d828411 100644 --- a/superkaramba/src/karamba.cpp +++ b/superkaramba/src/karamba.cpp @@ -988,6 +988,26 @@ void karamba::setSensor(const LineParser& lineParser, Meter* meter) } + if (sens == "GPU") + { + TQString gpuId = lineParser.getString("GPU"); + TQString gpuDriver = lineParser.getString("DRIVER"); + TQString sensorId = TQString("GPU_%1_%2").arg(gpuDriver, gpuId); + sensor = sensorMap[sensorId]; + if (sensor == 0) + { + int interval = lineParser.getInt("INTERVAL"); + interval = (interval == 0) ? 1000 : interval; + sensor = (sensorMap[sensorId] = new GPUSensor(gpuDriver, gpuId, interval)); + sensorList->append(sensor); + } + + SensorParams *sp = new SensorParams(meter); + sp->addParam("FORMAT", m_theme.locale()->translate(lineParser.getString("FORMAT").ascii())); + sensor->addMeter(sp); + sensor->setMaxValue(sp); + } + if( sens == "MEMORY" ) { sensor = sensorMap["MEMORY"]; diff --git a/superkaramba/src/karamba.h b/superkaramba/src/karamba.h index 57843d7..77f8f5c 100644 --- a/superkaramba/src/karamba.h +++ b/superkaramba/src/karamba.h @@ -82,6 +82,7 @@ #include "uptimesensor.h" #include "memsensor.h" #include "cpusensor.h" +#include "gpusensor.h" #include "networksensor.h" #include "xmmssensor.h" #include "noatunsensor.h" @@ -112,7 +113,7 @@ class LineParser; class karamba : public TQWidget { TQ_OBJECT - + public: karamba(TQString fn, TQString name, bool reloading = false, @@ -327,7 +328,7 @@ private slots: class DesktopChangeSlot : public TQObject { TQ_OBJECT - + public: DesktopChangeSlot(TQObject *parent, int desktop_id); @@ -348,7 +349,7 @@ class DesktopChangeSlot : public TQObject class SignalBridge : public TQObject { TQ_OBJECT - + public: SignalBridge(TQObject* parent, TQString, TDEActionCollection*); -- cgit v1.2.1