From de195cbf0b8c27577e9c98ecf393dcb26b0dc85b Mon Sep 17 00:00:00 2001 From: jussi Date: Fri, 25 Jan 2019 15:30:23 +0200 Subject: [PATCH] Start adding GPU feature detection to the UI --- mainwindow.cpp | 98 ++++++++++++++++++++++++------------------- mainwindow.h | 4 ++ nvidia.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++------- nvidia.h | 18 +++++++- 4 files changed, 171 insertions(+), 60 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index f96f1f0..394205c 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -17,40 +17,56 @@ MainWindow::MainWindow(QWidget *parent) : queryGPUSettings(); loadProfileSettings(); queryDriverSettings(); - //getGPUName(); queryGPUs(); setupMonitorTab(); setupGraphMonitorTab(); tabHandler(ui->tabWidget->currentIndex()); - ui->frequencySlider->setRange(minCoreClkOfsInt, maxCoreClkOfsInt); - ui->frequencySpinBox->setRange(minCoreClkOfsInt, maxCoreClkOfsInt); - ui->frequencySlider->setValue(coreFreqOfsInt); - ui->frequencySpinBox->setValue(coreFreqOfsInt); + // Create persistent nvidia pointer + nvidia *nvd = new nvidia; + nv = nvd; + nv->setupXNVCtrl(); + nv->setupNVML(0); + nv->queryGPUFeatures(); + qDebug() << nv->GPUList.size() << nv->GPUList[0].name << "gpus from main"; + + // Enable sliders according to GPU properties + if (nv->GPUList[0].overClockAvailable) { + ui->frequencySlider->setRange(nv->GPUList[0].minCoreClkOffset, nv->GPUList[0].maxCoreClkOffset); + ui->frequencySpinBox->setRange(nv->GPUList[0].minCoreClkOffset, nv->GPUList[0].maxCoreClkOffset); + ui->frequencySlider->setValue(coreFreqOfsInt); + ui->frequencySpinBox->setValue(coreFreqOfsInt); + + ui->memClkSlider->setRange(nv->GPUList[0].minMemClkOffset, nv->GPUList[0].maxMemClkOffset); + ui->memClkSpinBox->setRange(nv->GPUList[0].minMemClkOffset, nv->GPUList[0].maxMemClkOffset); + ui->memClkSlider->setValue(memClkOfsInt); + ui->memClkSpinBox->setValue(memClkOfsInt); + } else { + ui->frequencySlider->setEnabled(false); + ui->frequencySpinBox->setEnabled(false); + } ui->powerLimSlider->setRange(minPowerLimInt, maxPowerLimInt); ui->powerLimSpinBox->setRange(minPowerLimInt, maxPowerLimInt); ui->powerLimSlider->setValue(curPowerLimInt); ui->powerLimSpinBox->setValue(curPowerLimInt); - ui->memClkSlider->setRange(minMemClkOfsInt, maxMemClkOfsInt); - ui->memClkSpinBox->setRange(minMemClkOfsInt, maxMemClkOfsInt); - ui->memClkSlider->setValue(memClkOfsInt); - ui->memClkSpinBox->setValue(memClkOfsInt); - - ui->voltageSlider->setRange(minVoltOfsInt, maxVoltOfsInt); - ui->voltageSpinBox->setRange(minVoltOfsInt, maxVoltOfsInt); - ui->voltageSlider->setValue(voltOfsInt); - ui->voltageSpinBox->setValue(voltOfsInt); + if (nv->GPUList[0].overVoltAvailable) { + ui->voltageSlider->setRange(nv->GPUList[0].minVoltageOffset, nv->GPUList[0].maxVoltageOffset); + ui->voltageSpinBox->setRange(nv->GPUList[0].minVoltageOffset, nv->GPUList[0].maxVoltageOffset); + ui->voltageSlider->setValue(voltOfsInt); + ui->voltageSpinBox->setValue(voltOfsInt); + } else { + ui->voltageSlider->setEnabled(false); + ui->voltageSpinBox->setEnabled(false); + } ui->fanSlider->setValue(fanSpeed); ui->fanSpinBox->setValue(fanSpeed); ui->fanSlider->setRange(0, 100); ui->fanSpinBox->setRange(0, 100); - //QTimer *fanUpdateTimer = new QTimer(this); connect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(fanSpeedUpdater())); - //connect(fanUpdateTimer, SIGNAL(timeout()), this, SLOT(tempUpdater())); fanUpdateTimer->start(2000); connect(ui->frequencySpinBox, SIGNAL(valueChanged(int)), SLOT(resetTimer())); @@ -60,9 +76,6 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(tabHandler(int))); connect(monitorUpdater, SIGNAL(timeout()), SLOT(updateMonitor())); - - nvidia nv; - nv.setupXNVCtrl(); } MainWindow::~MainWindow() @@ -322,15 +335,31 @@ void MainWindow::setupGraphMonitorTab() } void MainWindow::updateMonitor() { - // This function takes around 300ms to complete, so it would be smoother to execute it in another thread + // Update the values for plots + nv->queryGPUTemp(0); + nv->queryGPUPowerDraw(0); + nv->queryGPUFrequencies(0); + nv->queryGPUUtils(0); + nv->queryGPUVoltage(0); + nv->queryGPUFanSpeed(0); - monitor mon; + plotCmdsList[0].valueq = nv->GPUList[0].temp; + plotCmdsList[1].valueq = nv->GPUList[0].powerDraw/1000; + plotCmdsList[2].valueq = nv->GPUList[0].coreFreq; + plotCmdsList[3].valueq = nv->GPUList[0].memFreq; + plotCmdsList[4].valueq = nv->GPUList[0].coreUtil; + plotCmdsList[5].valueq = nv->GPUList[0].memUtil; + plotCmdsList[6].valueq = nv->GPUList[0].voltage/1000; + plotCmdsList[7].valueq = nv->GPUList[0].fanSpeed; + + qDebug() << monitorUpdater->remainingTime(); + //monitor mon; //QThread *thread = new QThread(this); //mon.moveToThread(thread); //thread->start(); - mon.queryValues(); - fanSpeedUpdater(); - gputemp->setText(1, mon.temp + "°C"); + //mon.queryValues(); + //fanSpeedUpdater(); + /*gputemp->setText(1, mon.temp + "°C"); powerdraw->setText(1, mon.powerdraw + "W"); voltage->setText(1, mon.voltage + "mV"); coreclock->setText(1, mon.coreclock + " MHz"); @@ -338,7 +367,7 @@ void MainWindow::updateMonitor() coreutil->setText(1, mon.coreutil + " %"); memutil->setText(1, mon.memutil + " %"); fanspeed->setText(1, QString::number(fanSpeed) + " %"); - memusage->setText(1, mon.usedmem + "/" + mon.totalmem); + memusage->setText(1, mon.usedmem + "/" + mon.totalmem);*/ // Decrement all time values by one @@ -355,15 +384,6 @@ void MainWindow::updateMonitor() if (qv_time.size() > plotVectorSize) { qv_time.removeFirst(); } - // Update the values for plots - plotCmdsList[0].valueq = mon.temp.toDouble(); - plotCmdsList[1].valueq = mon.powerdraw.toDouble(); - plotCmdsList[2].valueq = mon.coreclock.toDouble(); - plotCmdsList[3].valueq = mon.memclock.toDouble(); - plotCmdsList[4].valueq = mon.coreutil.toDouble(); - plotCmdsList[5].valueq = mon.memutil.toDouble(); - plotCmdsList[6].valueq = mon.voltage.toDouble(); - plotCmdsList[7].valueq = fanSpeed; for (int i=0; istart(1000); QPoint cursor = event->pos(); - //qDebug() << childAt(cursor); - //QWidget *widget = childAt(cursor); - //QCustomPlot *plot = widget->findChild(QString(), Qt::FindDirectChildrenOnly); - //plot->xAxis->setRange(-15, 0); int plotIndex = 0; for (int i=0; ixAxis->pixelToCoord(cursor.x()); - //qDebug() << pointerxcoord << plotVectorSize; plotCmdsList[plotIndex].tracer->position->setCoords(pointerxcoord, plotCmdsList[plotIndex].plot->yAxis->range().upper); // Find the y-value for the corresponding coordinate int valIndex = 0; @@ -467,8 +481,6 @@ void MainWindow::plotHovered(QMouseEvent *event) valIndex = i; } } - //qDebug() << plotCmdsList[plotIndex].vector[valIndex]; - //QCPItemText *text = new QCPItemText(plotCmdsList[plotIndex].plot); plotCmdsList[plotIndex].valText->setText(QString::number(plotCmdsList[plotIndex].vector[valIndex])); // Make the text stay inside the plot if (pointerxcoord > -plotVectorSize*0.06) { @@ -478,7 +490,7 @@ void MainWindow::plotHovered(QMouseEvent *event) } else { plotCmdsList[plotIndex].valText->position->setCoords(pointerxcoord, plotCmdsList[plotIndex].plot->yAxis->range().upper - plotCmdsList[plotIndex].plot->yAxis->range().size()*0.05); } - //QThread::msleep(10); + QThread::msleep(10); } else { // If the cursor is not within the x-range, clear the text plotCmdsList[plotIndex].valText->setText(""); diff --git a/mainwindow.h b/mainwindow.h index 7826936..71ace2e 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -7,6 +7,7 @@ #include #include #include +#include "nvidia.h" //#include namespace Ui { @@ -158,6 +159,7 @@ private: bool noProfiles = true; QStringList UUIDList; QString latestUUID; + nvidia *nv; QTimer *resettimer = new QTimer(this); QTimer *fanUpdateTimer = new QTimer(this); @@ -242,6 +244,8 @@ private: plotCmds voltageplot; plotCmds fanspeedplot; QVector plotCmdsList; + + }; #endif // MAINWINDOW_H diff --git a/nvidia.cpp b/nvidia.cpp index 14bf375..bcb3cc6 100644 --- a/nvidia.cpp +++ b/nvidia.cpp @@ -9,7 +9,6 @@ nvidia::nvidia(QObject *parent) : QObject(parent) } bool nvidia::setupXNVCtrl() { - setupNVML(); // Open the x-server connection and check if the extension exists dpy = XOpenDisplay(nullptr); Bool ret; @@ -39,7 +38,8 @@ void nvidia::queryGPUCount() GPU gpu; GPUList.append(gpu); } - qDebug() << gpuCount; + qDebug() << GPUList.size() << "gpus"; + //setupNVML(0); } void nvidia::queryGPUNames() { @@ -148,17 +148,26 @@ void nvidia::queryGPUFeatures() qDebug() << "fanctl on"; GPUList[i].manualFanCtrl = true; } + // Query amount of VRAM + ret = XNVCTRLQueryTargetAttribute(dpy, + NV_CTRL_TARGET_TYPE_GPU, + i, + 0, + NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY, + &GPUList[i].totalVRAM); + qDebug() << GPUList[i].totalVRAM << "vram"; } - queryGPUVoltage(0); - queryGPUTemp(0); - queryGPUFrequencies(0); - queryGPUFanSpeed(0); + //queryGPUVoltage(0); + //queryGPUTemp(0); + //queryGPUFrequencies(0); + //queryGPUFanSpeed(0); + //queryGPUUsedVRAM(0); //assignGPUFanSpeed(0, 60); //assignGPUFreqOffset(0, 10); //assignGPUMemClockOffset(0, 10); //assignGPUVoltageOffset(0, 5000); - assignGPUFanCtlMode(0, NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE); + //assignGPUFanCtlMode(0, NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE); } void nvidia::queryGPUVoltage(int GPUIndex) { @@ -176,6 +185,7 @@ void nvidia::queryGPUVoltage(int GPUIndex) } void nvidia::queryGPUTemp(int GPUIndex) { + qDebug() << GPUList.size(); Bool ret; ret = XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_THERMAL_SENSOR, @@ -183,6 +193,9 @@ void nvidia::queryGPUTemp(int GPUIndex) 0, NV_CTRL_THERMAL_SENSOR_READING, &GPUList[GPUIndex].temp); + if (!ret) { + qDebug() << "failed to query GPU temperature"; + } qDebug() << GPUList[GPUIndex].temp; } void nvidia::queryGPUFrequencies(int GPUIndex) @@ -216,6 +229,19 @@ void nvidia::queryGPUFanSpeed(int GPUIndex) qDebug() << GPUList[GPUIndex].fanSpeed; } +void nvidia::queryGPUUsedVRAM(int GPUIndex) +{ + Bool ret = XNVCTRLQueryTargetAttribute(dpy, + NV_CTRL_TARGET_TYPE_GPU, + GPUIndex, + 0, + NV_CTRL_USED_DEDICATED_GPU_MEMORY, + &GPUList[GPUIndex].usedVRAM); + if (!ret) { + qDebug() << "failed to query used VRAM"; + } + qDebug() << GPUList[GPUIndex].usedVRAM << "usedvram"; +} bool nvidia::assignGPUFanSpeed(int GPUIndex, int targetValue) { Bool ret; @@ -283,21 +309,74 @@ bool nvidia::assignGPUVoltageOffset(int GPUIndex, int targetValue) qDebug() << temp; return true; }*/ -bool nvidia::setupNVML() +bool nvidia::setupNVML(int GPUIndex) { - nvmlDevice_t dev; + nvmlDevice_t *dev = new nvmlDevice_t; + device = dev; nvmlReturn_t ret = nvmlInit(); - int i; char name[64]; - nvmlDeviceGetHandleByIndex(i, &dev); - nvmlDeviceGetName(dev, name, sizeof(name)/sizeof(name[0])); + nvmlDeviceGetHandleByIndex(GPUIndex, dev); + //nvmlDeviceGetName(dev, name, sizeof(name)/sizeof(name[0])); qDebug() << name << "from nvml"; if (NVML_SUCCESS != ret) { return false; } + //queryGPUUtils(0); + //queryGPUPowerLimitLimits(0); + //queryGPUPowerDraw(0); + //qDebug() << assignGPUPowerLimit(150000); + return true; +} +void nvidia::queryGPUUtils(int GPUIndex) +{ + nvmlUtilization_t utils; + nvmlReturn_t ret = nvmlDeviceGetUtilizationRates(*device, &utils); + if (NVML_SUCCESS != ret) { + qDebug() << "failed to query GPU utilizations"; + } + qDebug() << utils.gpu << utils.memory << "utils"; + GPUList[GPUIndex].memUtil = utils.memory; + GPUList[GPUIndex].coreUtil = utils.gpu; +} +void nvidia::queryGPUPowerDraw(int GPUIndex) +{ + uint usg; + nvmlReturn_t ret = nvmlDeviceGetPowerUsage(*device, &usg); + if (NVML_SUCCESS != ret) { + qDebug() << "failed to query power usage"; + } else { + GPUList[GPUIndex].powerDraw = usg; + qDebug() << usg << "pwrusg"; + } +} +void nvidia::queryGPUPowerLimitLimits(int GPUIndex) +{ + uint maxlim; + uint minlim; + nvmlReturn_t ret = nvmlDeviceGetPowerManagementLimitConstraints(*device, &minlim, &maxlim); + if (NVML_SUCCESS != ret) { + qDebug() << "failed to query power limit constraints"; + } else { + GPUList[GPUIndex].minPowerLim = minlim; + GPUList[GPUIndex].maxPowerLim = maxlim; + qDebug() << minlim << maxlim << "powerlims"; + } +} +void nvidia::queryGPUPowerLimit(int GPUIndex) +{ + uint lim; + nvmlReturn_t ret = nvmlDeviceGetPowerManagementLimit(*device, &lim); + if (NVML_SUCCESS != ret) { + qDebug() << "failed to query power limit"; + } else { + GPUList[GPUIndex].powerLim = lim; + } +} +bool nvidia::assignGPUPowerLimit(uint targetValue) +{ + nvmlReturn_t ret = nvmlDeviceSetPowerManagementLimit(*device, targetValue); + if (NVML_SUCCESS != ret) { + return false; + } return true; } -void nvidia::queryGPUUtils(int GPUIndex) -{ - -} diff --git a/nvidia.h b/nvidia.h index 4896355..8e43712 100644 --- a/nvidia.h +++ b/nvidia.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "/opt/cuda/include/nvml.h" class nvidia : public QObject @@ -38,6 +39,12 @@ public: int temp; int voltage; int fanSpeed; + uint powerDraw; + uint coreUtil; + uint memUtil; + uint minPowerLim; + uint maxPowerLim; + uint powerLim; int totalVRAM; int usedVRAM; @@ -46,11 +53,13 @@ public: int gpuCount = 0; private: Display *dpy; + + nvmlDevice_t *device; signals: public slots: bool setupXNVCtrl(); - bool setupNVML(); + bool setupNVML(int GPUIndex); void queryGPUCount(); void queryGPUNames(); void queryGPUUIDs(); @@ -59,13 +68,20 @@ public slots: void queryGPUTemp(int GPUIndex); void queryGPUFrequencies(int GPUIndex); void queryGPUFanSpeed(int GPUIndex); + void queryGPUUsedVRAM(int GPUIndex); + void queryGPUUtils(int GPUIndex); + void queryGPUPowerDraw(int GPUIndex); + void queryGPUPowerLimit(int GPUIndex); + void queryGPUPowerLimitLimits(int GPUIndex); bool assignGPUFanSpeed(int GPUIndex, int targetValue); bool assignGPUFanCtlMode(int GPUIndex, int targetValue); bool assignGPUFreqOffset(int GPUIndex, int targetValue); bool assignGPUMemClockOffset(int GPUIndex, int targetValue); bool assignGPUVoltageOffset(int GPUIndex, int targetValue); + // NVML functions know the GPU index already based on the dev object passed in setupNVML() + bool assignGPUPowerLimit(uint targetValue); private slots: };