refactor hardwareinfo created, move gpu stuff to own file

This commit is contained in:
Crystian
2024-01-14 17:54:55 +01:00
parent 0be8352417
commit 25cdf36abc
8 changed files with 245 additions and 137 deletions
+3 -1
View File
@@ -1 +1,3 @@
from .monitor import *
from .monitor import *
from .hdd import *
from .gpu import *
+35 -76
View File
@@ -1,6 +1,3 @@
import platform
import cpuinfo
import psutil
import torch
import pynvml
import comfy.model_management
@@ -8,10 +5,14 @@ import comfy.model_management
from ..core import logger
class CStats:
def getGPUsInfo():
gpus = []
return gpus
class CGPUInfo:
"""
This is only class to get information from hardware.
Specially for share it to other software.
This class is responsible for getting information from GPU (ONLY).
"""
nvidia = False
pynvmlLoaded = False
@@ -19,25 +20,11 @@ class CStats:
torchDevice = 'cpu'
cudaDevice = 'cpu'
cudaDevicesFound = 0
switchCPU = False
switchGPU = False
switchHDD = False
switchRAM = False
switchVRAM = False
whichHDD = 'C:\\'
def __init__(self, switchCPU=False, switchGPU=False, switchHDD=False, switchRAM=False, switchVRAM=False):
self.switchCPU = switchCPU
self.switchGPU = switchGPU
self.switchHDD = switchHDD
self.switchRAM = switchRAM
self.switchVRAM = switchVRAM
specName = 'CPU: ' + cpuinfo.get_cpu_info().get('brand_raw', "Unknown")
specArch = 'Arch: ' + cpuinfo.get_cpu_info().get('arch_string_raw', "Unknown")
specOs = 'OS: ' + str(platform.system()) + ' ' + str(platform.release())
logger.info(f"{specName} - {specArch} - {specOs}")
def __init__(self):
logger.debug('CGPUInfo init')
try:
pynvml.nvmlInit()
self.pynvmlLoaded = True
@@ -45,40 +32,38 @@ class CStats:
self.pynvmlLoaded = False
logger.error('Could not init pynvml.' + str(e))
self.diagnostic()
if self.pynvmlLoaded and pynvml.nvmlDeviceGetCount() > 0:
self.cudaDevicesFound = pynvml.nvmlDeviceGetCount()
self.nvidia = True
logger.info(
f'NVIDIA Driver detected - {pynvml.nvmlSystemGetDriverVersion()} - {comfy.model_management.get_torch_device_name(comfy.model_management.get_torch_device())}')
else:
logger.warn('No NVIDIA GPU detected.')
def buildStatsData(self):
cpu = -1
ramTotal = -1
ramUsed = -1
ramUsedPercent = -1
hddTotal = -1
hddUsed = -1
hddUsedPercent = -1
try:
self.torchDevice = comfy.model_management.get_torch_device_name(comfy.model_management.get_torch_device())
except Exception as e:
logger.error('Could not pick default device.' + str(e))
self.cudaDevice = 'cpu' if self.torchDevice == 'cpu' else 'cuda'
self.cudaAvailable = torch.cuda.is_available()
if self.nvidia and self.cudaAvailable and self.torchDevice == 'cpu':
logger.warn('CUDA is available, but torch is using CPU.')
def getStatus(self):
# logger.debug('CGPUInfo getStatus')
gpuUtilization = -1
vramUsed = -1
vramTotal = -1
vramPercent = -1
if self.switchCPU:
cpu = psutil.cpu_percent()
if self.switchRAM:
ram = psutil.virtual_memory()
ramTotal = ram.total
ramUsed = ram.used
ramUsedPercent = ram.percent
if self.switchHDD:
hdd = psutil.disk_usage(self.whichHDD)
hddTotal = hdd.total
hddUsed = hdd.used
hddUsedPercent = hdd.percent
deviceType = 'cpu'
gpuType = ''
gpus = []
if self.cudaDevice == 'cpu':
gpuType = 'cpu'
gpus.append({
'gpu_utilization': -1,
'vram_total': -1,
@@ -86,7 +71,7 @@ class CStats:
'vram_used_percent': -1,
})
else:
deviceType = self.cudaDevice
gpuType = self.cudaDevice
if self.pynvmlLoaded and self.nvidia and self.cudaAvailable:
for deviceIndex in range(self.cudaDevicesFound):
@@ -104,7 +89,7 @@ class CStats:
vramUsed = memory.used
vramTotal = memory.total
# device = torch.device(deviceType)
# device = torch.device(gpuType)
# vramUsed = torch.cuda.memory_allocated(device)
# vramTotal = torch.cuda.get_device_properties(device).total_memory
@@ -118,32 +103,6 @@ class CStats:
})
return {
'cpu_utilization': cpu,
'ram_total': ramTotal,
'ram_used': ramUsed,
'ram_used_percent': ramUsedPercent,
'hdd_total': hddTotal,
'hdd_used': hddUsed,
'hdd_used_percent': hddUsedPercent,
'device_type': deviceType,
'device_type': gpuType,
'gpus': gpus,
}
def diagnostic(self):
if self.pynvmlLoaded and pynvml.nvmlDeviceGetCount() > 0:
self.cudaDevicesFound = pynvml.nvmlDeviceGetCount()
self.nvidia = True
logger.info(f'NVIDIA Driver detected - {pynvml.nvmlSystemGetDriverVersion()} - {comfy.model_management.get_torch_device_name(comfy.model_management.get_torch_device())}')
else:
logger.warn('No NVIDIA GPU detected.')
try:
self.torchDevice = comfy.model_management.get_torch_device_name(comfy.model_management.get_torch_device())
except Exception as e:
logger.error('Could not pick default device.' + str(e))
self.cudaDevice = 'cpu' if self.torchDevice == 'cpu' else 'cuda'
self.cudaAvailable = torch.cuda.is_available()
if self.nvidia and self.cudaAvailable and self.torchDevice == 'cpu':
logger.warn('CUDA is available, but torch is using CPU.')
+83
View File
@@ -0,0 +1,83 @@
import platform
import cpuinfo
import psutil
from .gpu import CGPUInfo
from ..core import logger
class CHardwareInfo:
"""
This is only class to get information from hardware.
Specially for share it to other software.
"""
switchCPU = False
switchHDD = False
switchRAM = False
whichHDD = 'C:\\'
@property
def switchGPU(self):
return self.GPUInfo.switchGPU
@switchGPU.setter
def switchGPU(self, value):
self.GPUInfo.switchGPU = value
@property
def switchVRAM(self):
return self.GPUInfo.switchVRAM
@switchVRAM.setter
def switchVRAM(self, value):
self.GPUInfo.switchVRAM = value
def __init__(self, switchCPU=False, switchGPU=False, switchHDD=False, switchRAM=False, switchVRAM=False):
self.switchCPU = switchCPU
self.switchHDD = switchHDD
self.switchRAM = switchRAM
specName = 'CPU: ' + cpuinfo.get_cpu_info().get('brand_raw', "Unknown")
specArch = 'Arch: ' + cpuinfo.get_cpu_info().get('arch_string_raw', "Unknown")
specOs = 'OS: ' + str(platform.system()) + ' ' + str(platform.release())
logger.info(f"{specName} - {specArch} - {specOs}")
self.GPUInfo = CGPUInfo()
self.switchGPU = switchGPU
self.switchVRAM = switchVRAM
def getStatus(self):
cpu = -1
ramTotal = -1
ramUsed = -1
ramUsedPercent = -1
hddTotal = -1
hddUsed = -1
hddUsedPercent = -1
if self.switchCPU:
cpu = psutil.cpu_percent()
if self.switchRAM:
ram = psutil.virtual_memory()
ramTotal = ram.total
ramUsed = ram.used
ramUsedPercent = ram.percent
if self.switchHDD:
hdd = psutil.disk_usage(self.whichHDD)
hddTotal = hdd.total
hddUsed = hdd.used
hddUsedPercent = hdd.percent
getStatus = self.GPUInfo.getStatus()
return {
'cpu_utilization': cpu,
'ram_total': ramTotal,
'ram_used': ramUsed,
'ram_used_percent': ramUsedPercent,
'hdd_total': hddTotal,
'hdd_used': hddUsed,
'hdd_used_percent': hddUsedPercent,
'device_type': getStatus['device_type'],
'gpus': getStatus['gpus'],
}
+10
View File
@@ -0,0 +1,10 @@
import psutil
from ..core import logger
def getHDDsInfo():
hdds = []
logger.debug('Getting HDDs info...')
for partition in psutil.disk_partitions():
hdds.append(partition.mountpoint)
return hdds
+4 -4
View File
@@ -2,7 +2,7 @@ import asyncio
import server
import time
import threading
from .stats import CStats
from .hardware import CHardwareInfo
from ..core import logger
@@ -13,11 +13,11 @@ class CMonitor:
monitorThread = None
threadController = threading.Event()
rate = 0
stats = None
hardwareInfo = None
def __init__(self, rate=5, switchCPU=False, switchGPU=False, switchHDD=False, switchRAM=False, switchVRAM=False):
self.rate = rate
self.stats = CStats(switchCPU, switchGPU, switchHDD, switchRAM, switchVRAM)
self.hardwareInfo = CHardwareInfo(switchCPU, switchGPU, switchHDD, switchRAM, switchVRAM)
self.startMonitor()
@@ -28,7 +28,7 @@ class CMonitor:
def monitorLoop(self):
while self.rate > 0 and not self.threadController.is_set():
data = self.stats.buildStatsData()
data = self.hardwareInfo.getStatus()
# print(data)
asyncio.run(self.send_message(data))
time.sleep(self.rate)
+16 -13
View File
@@ -1,8 +1,7 @@
import psutil
from server import PromptServer
from aiohttp import web
from ..core import logger
from ..general.monitor import cmonitor
from ..general import cmonitor, getHDDsInfo, getGPUsInfo
@PromptServer.instance.routes.patch("/crystools/monitor")
async def newSettings(request):
@@ -26,42 +25,42 @@ async def newSettings(request):
if type(switchCPU) is not bool:
raise Exception('switchCPU must be an boolean.')
cmonitor.stats.switchCPU = switchCPU
cmonitor.hardwareInfo.switchCPU = switchCPU
if 'switchGPU' in settings is not None:
switchGPU = settings['switchGPU']
if type(switchGPU) is not bool:
raise Exception('switchGPU must be an boolean.')
cmonitor.stats.switchGPU = switchGPU
cmonitor.hardwareInfo.switchGPU = switchGPU
if 'switchHDD' in settings is not None:
switchHDD = settings['switchHDD']
if type(switchHDD) is not bool:
raise Exception('switchHDD must be an boolean.')
cmonitor.stats.switchHDD = switchHDD
cmonitor.hardwareInfo.switchHDD = switchHDD
if 'switchRAM' in settings is not None:
switchRAM = settings['switchRAM']
if type(switchRAM) is not bool:
raise Exception('switchRAM must be an boolean.')
cmonitor.stats.switchRAM = switchRAM
cmonitor.hardwareInfo.switchRAM = switchRAM
if 'switchVRAM' in settings is not None:
switchVRAM = settings['switchVRAM']
if type(switchVRAM) is not bool:
raise Exception('switchVRAM must be an boolean.')
cmonitor.stats.switchVRAM = switchVRAM
cmonitor.hardwareInfo.switchVRAM = switchVRAM
if 'whichHDD' in settings is not None:
whichHDD = settings['whichHDD']
if type(whichHDD) is not str:
raise Exception('whichHDD must be an string.')
cmonitor.stats.whichHDD = whichHDD
cmonitor.hardwareInfo.whichHDD = whichHDD
return web.Response(status=200)
@@ -92,14 +91,18 @@ async def monitorSwitch(request):
@PromptServer.instance.routes.get("/crystools/monitor/HDD")
async def getHDDs(request):
def getHDDs(request):
try:
hdds = []
return web.json_response(getHDDsInfo())
except Exception as e:
logger.error(e)
return web.Response(status=400, text=str(e))
for partition in psutil.disk_partitions():
hdds.append(partition.mountpoint)
return web.json_response(hdds)
@PromptServer.instance.routes.get("/crystools/monitor/GPU")
def getGPUs(request):
try:
return web.json_response(getGPUsInfo())
except Exception as e:
logger.error(e)
return web.Response(status=400, text=str(e))
+39 -20
View File
@@ -296,25 +296,6 @@ class CrystoolsMonitor {
});
},
});
void this.getHDDsFromServer().then((data) => {
const which = app.ui.settings.getSettingValue(this.idWhichHDD, this.defaultWhichHDD);
app.ui.settings.addSetting({
id: this.idWhichHDD,
name: this.menuPrefix + 'Partition to show (HDD)',
type: 'combo',
defaultValue: this.defaultWhichHDD,
options: (value) => data.map((m) => ({
value: m,
text: m,
selected: !value ? m === which : m === value,
})),
onChange: async (value) => {
await this.updateServer({
whichHDD: value,
});
},
});
});
app.ui.settings.addSetting({
id: this.idInputRate,
name: this.menuPrefix + 'Monitors refresh rate (in seconds) [menu]',
@@ -387,6 +368,28 @@ class CrystoolsMonitor {
}
},
});
void this.getHDDsFromServer().then((data) => {
const which = app.ui.settings.getSettingValue(this.idWhichHDD, this.defaultWhichHDD);
app.ui.settings.addSetting({
id: this.idWhichHDD,
name: this.menuPrefix + 'Partition to show (HDD)',
type: 'combo',
defaultValue: this.defaultWhichHDD,
options: (value) => data.map((m) => ({
value: m,
text: m,
selected: !value ? m === which : m === value,
})),
onChange: async (value) => {
await this.updateServer({
whichHDD: value,
});
},
});
});
void this.getGPUsFromServer().then((data) => {
console.log('data', data);
});
}
});
Object.defineProperty(this, "updateServer", {
@@ -410,7 +413,23 @@ class CrystoolsMonitor {
configurable: true,
writable: true,
value: async () => {
const resp = await api.fetchApi('/crystools/monitor/HDD', {
return this.getDataFromServer('HDD');
}
});
Object.defineProperty(this, "getGPUsFromServer", {
enumerable: true,
configurable: true,
writable: true,
value: async () => {
return this.getDataFromServer('GPU');
}
});
Object.defineProperty(this, "getDataFromServer", {
enumerable: true,
configurable: true,
writable: true,
value: async (what) => {
const resp = await api.fetchApi(`/crystools/monitor/${what}`, {
method: 'GET',
cache: 'no-store',
});
+55 -23
View File
@@ -120,28 +120,6 @@ class CrystoolsMonitor {
},
});
void this.getHDDsFromServer().then((data: string[]): void => {
const which = app.ui.settings.getSettingValue(this.idWhichHDD, this.defaultWhichHDD);
app.ui.settings.addSetting({
id: this.idWhichHDD,
name: this.menuPrefix + 'Partition to show (HDD)',
type: 'combo',
defaultValue: this.defaultWhichHDD,
options: (value: string) =>
data.map((m) => ({
value: m,
text: m,
selected: !value ? m === which : m === value,
})),
onChange: async(value: string) => {
await this.updateServer({
whichHDD: value,
});
},
});
});
app.ui.settings.addSetting({
id: this.idInputRate,
name: this.menuPrefix + 'Monitors refresh rate (in seconds) [menu]',
@@ -218,6 +196,52 @@ class CrystoolsMonitor {
}
},
});
void this.getHDDsFromServer().then((data: string[]): void => {
const which = app.ui.settings.getSettingValue(this.idWhichHDD, this.defaultWhichHDD);
app.ui.settings.addSetting({
id: this.idWhichHDD,
name: this.menuPrefix + 'Partition to show (HDD)',
type: 'combo',
defaultValue: this.defaultWhichHDD,
options: (value: string) =>
data.map((m) => ({
value: m,
text: m,
selected: !value ? m === which : m === value,
})),
onChange: async(value: string) => {
await this.updateServer({
whichHDD: value,
});
},
});
});
void this.getGPUsFromServer().then((data: string[]): void => {
// const which = app.ui.settings.getSettingValue(this.idWhichHDD, this.defaultWhichHDD);
console.log('data', data);
// app.ui.settings.addSetting({
// id: this.idWhichHDD+2,
// name: this.menuPrefix + 'Partition to show (HDD)',
// type: 'combo',
// defaultValue: this.defaultWhichHDD,
// options: (value: string) =>
// data.map((m) => ({
// // value: m,
// // text: m,
// // selected: !value ? m === which : m === value,
// })),
// onChange: async(value: string) => {
// console.log('value', value);
// // await this.updateServer({
// // whichHDD: value,
// // });
// },
// });
});
};
updateServer = async(data: TStatsSettings): Promise<string> => {
@@ -233,7 +257,15 @@ class CrystoolsMonitor {
};
getHDDsFromServer = async(): Promise<string[]> => {
const resp = await api.fetchApi('/crystools/monitor/HDD', {
return this.getDataFromServer('HDD');
};
getGPUsFromServer = async(): Promise<string[]> => {
return this.getDataFromServer('GPU');
};
getDataFromServer = async(what: string): Promise<string[]> => {
const resp = await api.fetchApi(`/crystools/monitor/${what}`, {
method: 'GET',
cache: 'no-store',
});