diff --git a/proto/src/report.proto b/proto/src/report.proto index 6ace5708e..0e74e4724 100644 --- a/proto/src/report.proto +++ b/proto/src/report.proto @@ -34,7 +34,7 @@ message BootReport { } message CoreDetail { - int32 total_cores = 1; + int32 total_cores = 1; // physical cores int32 idle_cores = 2; int32 locked_cores = 3; int32 booked_cores = 4; @@ -43,6 +43,7 @@ message CoreDetail { // solely on rqd's end to store a map of reserved cores, but the data was never communicated to // the server. map reserved_cores = 5 [deprecated=true]; + int32 total_threads = 6; // logical cores } message CoreId { @@ -70,7 +71,7 @@ message RenderHost { bool nimby_locked = 3; // if nimby has locked the host due to user activity string facility= 4; // The name of the facility that the host is in int32 num_procs = 5; // the number of physical procs on this machine - int32 cores_per_proc = 6; // the number of cores per proc + int32 cores_per_proc = 6; // the number of physical cores per proc int64 total_swap = 7; // the total size of the swap in kB int64 total_mem = 8; // the total size of the main memory pool in kB int64 total_mcp = 9; // the total size of MCP in kB @@ -85,6 +86,7 @@ message RenderHost { int32 num_gpus = 18; // the number of physical GPU's int64 free_gpu_mem = 19; // the current amount of free gpu memory in kB int64 total_gpu_mem = 20; // the total size of gpu memory in kB + int32 threads_per_proc = 21; // the number of logical cores per proc }; message RunningFrameInfo { @@ -107,6 +109,7 @@ message RunningFrameInfo { int64 used_gpu_memory = 17; // kB ChildrenProcStats children = 18; //additional data about the running frame's child processes int64 used_swap_memory = 19; // kB + bool use_threads = 20; // whether the frame is requesting logical or physical cores }; message ChildrenProcStats { diff --git a/rqd/rqd/__main__.py b/rqd/rqd/__main__.py index 6295d4572..0ba244469 100755 --- a/rqd/rqd/__main__.py +++ b/rqd/rqd/__main__.py @@ -29,6 +29,7 @@ In /etc/opencue/rqd.conf (on Linux) or %LOCALAPPDATA%/OpenCue/rqd.conf (on Windows): [Override] OVERRIDE_CORES = 2 +OVERRIDE_THREADS = 4 OVERRIDE_PROCS = 3 OVERRIDE_MEMORY = 1000000 OVERRIDE_CUEBOT = cuebot1 cuebot2 cuebot3 diff --git a/rqd/rqd/rqconstants.py b/rqd/rqd/rqconstants.py index 0ce70b94e..82537155e 100644 --- a/rqd/rqd/rqconstants.py +++ b/rqd/rqd/rqconstants.py @@ -154,15 +154,16 @@ if '-c' in sys.argv: CONFIG_FILE = sys.argv[sys.argv.index('-c') + 1] -OVERRIDE_CORES = None # number of cores. ex: None or 8 -OVERRIDE_IS_DESKTOP = None # Force rqd to run in 'desktop' mode OVERRIDE_PROCS = None # number of physical cpus. ex: None or 2 +OVERRIDE_CORES = None # number of cores per cpu. ex: None or 8 +OVERRIDE_THREADS = None # number of threads per cpu. ex: None or 16 +OVERRIDE_IS_DESKTOP = None # Force rqd to run in 'desktop' mode OVERRIDE_MEMORY = None # in Kb OVERRIDE_NIMBY = None # True to turn on, False to turn off USE_NIMBY_PYNPUT = True # True pynput, False select OVERRIDE_HOSTNAME = None # Force to use this hostname ALLOW_GPU = False -LOAD_MODIFIER = 0 # amount to add/subtract from load +LOAD_MODIFIER = 0 # amount to add/subtract from load, makes the machine look busier to CueBot. LOG_FORMAT = '%(levelname)-9s openrqd-%(module)-10s: %(message)s' CONSOLE_LOG_LEVEL = logging.WARNING @@ -207,6 +208,8 @@ CUEBOT_GRPC_PORT = config.getint(__override_section, "CUEBOT_GRPC_PORT") if config.has_option(__override_section, "OVERRIDE_CORES"): OVERRIDE_CORES = config.getint(__override_section, "OVERRIDE_CORES") + if config.has_option(__override_section, "OVERRIDE_THREADS"): + OVERRIDE_THREADS = config.getint(__override_section, "OVERRIDE_THREADS") if config.has_option(__override_section, "OVERRIDE_PROCS"): OVERRIDE_PROCS = config.getint(__override_section, "OVERRIDE_PROCS") if config.has_option(__override_section, "OVERRIDE_MEMORY"): diff --git a/rqd/rqd/rqcore.py b/rqd/rqd/rqcore.py index e60d49365..59ccf07ab 100644 --- a/rqd/rqd/rqcore.py +++ b/rqd/rqd/rqcore.py @@ -68,6 +68,7 @@ def __init__(self, optNimbyoff=False): self.cores = opencue_proto.report_pb2.CoreDetail( total_cores=0, + total_threads=0, idle_cores=0, locked_cores=0, booked_cores=0, @@ -328,7 +329,10 @@ def killAllFrame(self, reason): def releaseCores(self, reqRelease, releaseHT=None, releaseGpus=None): """The requested number of cores are released @type reqRelease: int - @param reqRelease: Number of cores to release, 100 = 1 physical core""" + @param reqRelease: Number of cores to release, 100 = 1 physical core + @type releaseHT: str + @param releaseHT: The hyper-threading cores to release + """ with self.__threadLock: # pylint: disable=no-member self.cores.booked_cores -= reqRelease @@ -431,9 +435,11 @@ def launchFrame(self, runFrame): # pylint: enable=no-member if runFrame.environment.get('CUE_THREADABLE') == '1': - reserveHT = self.machine.reserveHT(runFrame.num_cores) - if reserveHT: - runFrame.attributes['CPU_LIST'] = reserveHT + cpu_list = self.machine.reserveCores( + coresCount=runFrame.num_cores, + logical=runFrame.use_threads) + if cpu_list: + runFrame.attributes['CPU_LIST'] = cpu_list if runFrame.num_gpus: reserveGpus = self.machine.reserveGpus(runFrame.num_gpus) diff --git a/rqd/rqd/rqmachine.py b/rqd/rqd/rqmachine.py index 610df78ee..20cf21964 100644 --- a/rqd/rqd/rqmachine.py +++ b/rqd/rqd/rqmachine.py @@ -24,7 +24,6 @@ from builtins import range from builtins import object -import codecs import ctypes import errno import logging @@ -37,6 +36,7 @@ import tempfile import time import traceback +import warnings # pylint: disable=import-error,wrong-import-position if platform.system() in ('Linux', 'Darwin'): @@ -58,6 +58,8 @@ import rqd.rqexceptions import rqd.rqswap import rqd.rqutil +if platform.system() == "Windows": + import rqd.rqwinutils log = logging.getLogger(__name__) @@ -79,11 +81,11 @@ def __init__(self, rqCore, coreInfo): # A dictionary built from /proc/cpuinfo containing # { : { : set([, , ...]), ... }, ... } - self.__procs_by_physid_and_coreid = {} + self.__threadid_by_cpuid_and_coreid = {} # A reverse mapping of the above. # { : (, ), ... } - self.__physid_and_coreid_by_proc = {} + self.__cpuid_and_coreid_by_threadid = {} if platform.system() == 'Linux': self.__vmstat = rqd.rqswap.VmStat() @@ -456,26 +458,33 @@ def _getProcSwap(self, pid): def getLoadAvg(self): """Returns average number of processes waiting to be served - for the last 1 minute multiplied by 100.""" + for the last 1 minute across all cores, x100 for cuebot.""" + loadAvg = 0 if platform.system() == "Linux": + # On linux, the load is the average number of processes in queue + # It helps measures the CPU utilization as well as disk i/o. with open(rqd.rqconstants.PATH_LOADAVG, "r", encoding='utf-8') as loadAvgFile: - loadAvg = int(float(loadAvgFile.read().split()[0]) * 100) - if self.__enabledHT(): - loadAvg = loadAvg // self.getHyperthreadingMultiplier() - loadAvg = loadAvg + rqd.rqconstants.LOAD_MODIFIER - loadAvg = max(loadAvg, 0) - return loadAvg - return 0 + loadAvg = float(loadAvgFile.read().split()[0]) * 100 + elif platform.system() in ("Windows", "Darwin"): + # On Windows and MacOS, we can only get the CPU usage. + # Here we get the sum of the CPU usage across all cores. + # (note: CueGui divides this value by the number of physical cores) + loadAvg = sum(psutil.cpu_percent(interval=2, percpu=True)) + if self.__enabledHT(): + loadAvg = loadAvg // self.getHyperthreadingMultiplier() + loadAvg += rqd.rqconstants.LOAD_MODIFIER + loadAvg = max(loadAvg, 0) + return int(loadAvg) @rqd.rqutil.Memoize def getBootTime(self): """Returns epoch when the system last booted""" - if platform.system() == "Linux": + if os.path.isfile(rqd.rqconstants.PATH_STAT): with open(rqd.rqconstants.PATH_STAT, "r", encoding='utf-8') as statFile: for line in statFile: if line.startswith("btime"): return int(line.split()[1]) - return 0 + return int(psutil.boot_time()) @rqd.rqutil.Memoize def getGpuCount(self): @@ -619,197 +628,197 @@ def testInitMachineStats(self, pathCpuInfo): return self.__renderHost, self.__coreInfo def __initMachineStats(self, pathCpuInfo=None): - """Updates static machine information during initialization""" + """Updates static machine information during initialization + + @type pathCpuInfo: str + @param pathCpuInfo: Path to a specific cpuinfo file + """ self.__renderHost.name = self.getHostname() self.__renderHost.boot_time = self.getBootTime() self.__renderHost.facility = rqd.rqconstants.DEFAULT_FACILITY self.__renderHost.attributes['SP_OS'] = rqd.rqconstants.SP_OS + # Get the total memory and swap self.updateMachineStats() - __numProcs = __totalCores = 0 - if platform.system() == "Linux" or pathCpuInfo is not None: - # Reads static information for mcp - mcpStat = os.statvfs(self.getTempPath()) - self.__renderHost.total_mcp = mcpStat.f_blocks * mcpStat.f_frsize // KILOBYTE - - # Reset mappings - self.__procs_by_physid_and_coreid = {} - self.__physid_and_coreid_by_proc = {} - - # Reads static information from /proc/cpuinfo - with open(pathCpuInfo or rqd.rqconstants.PATH_CPUINFO, "r", - encoding='utf-8') as cpuinfoFile: - currCore = {} - procsFound = [] - for line in cpuinfoFile: - lineList = line.strip().replace("\t", "").split(": ") - # A normal entry added to the singleCore dictionary - if len(lineList) >= 2: - currCore[lineList[0]] = lineList[1] - # The end of a processor block - elif lineList == ['']: - # Check for hyper-threading - hyperthreadingMultiplier = (int(currCore.get('siblings', '1')) - // int(currCore.get('cpu cores', '1'))) - - __totalCores += rqd.rqconstants.CORE_VALUE - if "core id" in currCore \ - and "physical id" in currCore \ - and not currCore["physical id"] in procsFound: - procsFound.append(currCore["physical id"]) - __numProcs += 1 - elif "core id" not in currCore: - __numProcs += 1 - - if 'physical id' in currCore and 'core id' in currCore: - # Keep track of what processors are on which core on - # which physical socket. - procid, physid, coreid = ( - currCore['processor'], - currCore['physical id'], - currCore['core id']) - self.__procs_by_physid_and_coreid \ - .setdefault(physid, {}) \ - .setdefault(coreid, set()).add(procid) - self.__physid_and_coreid_by_proc[procid] = physid, coreid - currCore = {} - - # An entry without data - elif len(lineList) == 1: - currCore[lineList[0]] = "" - - # Reads information from /proc/meminfo - with codecs.open(rqd.rqconstants.PATH_MEMINFO, "r", encoding="utf-8") as fp: - for line in fp: - if line.startswith("MemTotal"): - self.__renderHost.total_mem = int(line.split()[1]) - elif line.startswith("SwapTotal"): - self.__renderHost.total_swap = int(line.split()[1]) - elif platform.system() == 'Darwin': - # Reads static information for mcp - mcpStat = os.statvfs(self.getTempPath()) - self.__renderHost.total_mcp = mcpStat.f_blocks * mcpStat.f_frsize // KILOBYTE - hyperthreadingMultiplier = 1 - else: - hyperthreadingMultiplier = 1 - - if platform.system() == 'Windows': - logicalCoreCount, __numProcs, hyperthreadingMultiplier = self.__initStatsFromWindows() - __totalCores = logicalCoreCount * rqd.rqconstants.CORE_VALUE + # By default all systems will just have one proc/core + cpu_count = total_cores = total_threads = core_per_proc = thread_per_proc = 1 - # All other systems will just have one proc/core - if not __numProcs or not __totalCores: - __numProcs = 1 - __totalCores = rqd.rqconstants.CORE_VALUE + if platform.system() == "Linux" or pathCpuInfo is not None: + self.__initStatsLinux(pathCpuInfo) + (cpu_count, total_cores, total_threads, + core_per_proc, thread_per_proc) = self.count_cores() + elif platform.system() == 'Windows': + self.__initStatsWindows() + (cpu_count, total_cores, total_threads, + core_per_proc, thread_per_proc) = self.count_cores() + # Override values from rqd.conf if rqd.rqconstants.OVERRIDE_MEMORY is not None: log.warning("Manually overriding the total memory") self.__renderHost.total_mem = rqd.rqconstants.OVERRIDE_MEMORY - if rqd.rqconstants.OVERRIDE_CORES is not None: - log.warning("Manually overriding the number of reported cores") - __totalCores = rqd.rqconstants.OVERRIDE_CORES * rqd.rqconstants.CORE_VALUE - if rqd.rqconstants.OVERRIDE_PROCS is not None: log.warning("Manually overriding the number of reported procs") - __numProcs = rqd.rqconstants.OVERRIDE_PROCS - - # Don't report/reserve cores added due to hyperthreading - __totalCores = __totalCores // hyperthreadingMultiplier + cpu_count = rqd.rqconstants.OVERRIDE_PROCS - self.__coreInfo.idle_cores = __totalCores - self.__coreInfo.total_cores = __totalCores - self.__renderHost.num_procs = __numProcs - self.__renderHost.cores_per_proc = __totalCores // __numProcs - - if hyperthreadingMultiplier >= 1: - self.__renderHost.attributes['hyperthreadingMultiplier'] = str(hyperthreadingMultiplier) - - def __initStatsFromWindows(self): + if rqd.rqconstants.OVERRIDE_CORES is not None: + log.warning("Manually overriding the number of reported cores") + core_per_proc = rqd.rqconstants.OVERRIDE_CORES + total_cores = core_per_proc * cpu_count + if rqd.rqconstants.OVERRIDE_THREADS is None: + thread_per_proc = core_per_proc + total_threads = total_cores + + if rqd.rqconstants.OVERRIDE_THREADS is not None: + log.warning("Manually overriding the number of reported threads") + thread_per_proc = rqd.rqconstants.OVERRIDE_THREADS + total_threads = thread_per_proc * cpu_count + if rqd.rqconstants.OVERRIDE_CORES is None: + core_per_proc = thread_per_proc + total_cores = total_threads + + self.__coreInfo.idle_cores = total_cores * rqd.rqconstants.CORE_VALUE + # TODO: add idle_threads ? anyway we need to address reserving threads instead of cores. + self.__coreInfo.total_cores = total_cores * rqd.rqconstants.CORE_VALUE + self.__coreInfo.total_threads = total_threads * rqd.rqconstants.CORE_VALUE + self.__renderHost.num_procs = cpu_count + self.__renderHost.cores_per_proc = core_per_proc * rqd.rqconstants.CORE_VALUE + self.__renderHost.threads_per_proc = thread_per_proc * rqd.rqconstants.CORE_VALUE + + ht_multiplier = thread_per_proc / core_per_proc + if ht_multiplier >= 1: + self.__renderHost.attributes['hyperthreadingMultiplier'] = str(ht_multiplier) + + def count_cores(self): + """Counts the number of cores on the machine""" + cpu_count = len(self.__threadid_by_cpuid_and_coreid.keys()) + total_threads = len(self.__cpuid_and_coreid_by_threadid.keys()) + thread_per_proc = total_threads // cpu_count + total_cores = sum( + len(cores) for _, cores in self.__threadid_by_cpuid_and_coreid.items() + ) + core_per_proc = total_cores // cpu_count + + return cpu_count, total_cores, total_threads, core_per_proc, thread_per_proc + + def __initStatsLinux(self, pathCpuInfo=None): + """Init machine stats for Linux platforms. + + @type pathCpuInfo: str + @param pathCpuInfo: Path to a specific cpuinfo file + """ + coreInfo = [] + # Reads static information from /proc/cpuinfo + with (open(pathCpuInfo or rqd.rqconstants.PATH_CPUINFO, "r", + encoding='utf-8') as cpuinfoFile): + infoBlock = {} # Gets reset for each processor block + for line in cpuinfoFile: + lineList = line.strip().replace("\t", "").split(": ") + # A normal entry added to the singleCore dictionary + if len(lineList) >= 2: + infoBlock[lineList[0]] = lineList[1] + # An entry without data + elif len(lineList) == 1: + infoBlock[lineList[0]] = "" + # The end of a processor block + if lineList == ['']: + # Get relevant information from the block + logical_core_id = infoBlock['processor'] + cpu_id = infoBlock.get('physical id', infoBlock['processor']) + physical_core_id = infoBlock.get('core id', infoBlock['processor']) + # Save that and iterate + coreInfo.append((cpu_id, physical_core_id, logical_core_id)) + infoBlock.clear() + + self.__updateProcsMappings(coreInfo=coreInfo) + + def __initStatsWindows(self): """Init machine stats for Windows platforms. - - @rtype: tuple - @return: A 3-items tuple containing: - - the number of logical cores - - the number of physical processors - - the hyper-threading multiplier """ - # Windows memory information - stat = self.getWindowsMemory() - TEMP_DEFAULT = 1048576 - self.__renderHost.total_mcp = TEMP_DEFAULT - self.__renderHost.total_mem = int(stat.ullTotalPhys / 1024) - self.__renderHost.total_swap = int(stat.ullTotalPageFile / 1024) - - # Windows CPU information - self.__updateProcsMappingsFromWindows() - - logicalCoreCount = psutil.cpu_count(logical=True) - actualCoreCount = psutil.cpu_count(logical=False) - hyperThreadingMultiplier = logicalCoreCount // actualCoreCount + coreInfo = rqd.rqwinutils.get_logical_processor_information_ex() + self.__updateProcsMappings(coreInfo=coreInfo) - physicalProcessorCount = len(self.__procs_by_physid_and_coreid) - - return logicalCoreCount, physicalProcessorCount, hyperThreadingMultiplier - - def __updateProcsMappingsFromWindows(self): + def __updateProcsMappings(self, coreInfo): """ - Update `__procs_by_physid_and_coreid` and `__physid_and_coreid_by_proc` mappings - for Windows platforms. + Update `__threadid_by_cpuid_and_coreid` and `__cpuid_and_coreid_by_threadid` mappings. + + @type coreInfo: list[tuple[str, str, str]] + @param coreInfo: A list of tuples containing CPU ID, Physical Core ID, and Logical Core ID. + + Implementation detail: + One CPU has one or more physical cores, + and each physical core has one or more logical cores. + Some CPUs have hyper-threading, which means that each logical core is treated as + a separate core by the operating system, while being on the same physical core. + Hybrid CPUs have performance cores that are hyper-threaded, + and efficient cores that are mono-threaded. + On Windows, we can't detect each physical CPU, + so instead we use CPU groups (64 cores per group). """ - # Windows-specific - import wmi # pylint:disable=import-outside-toplevel,import-error # Reset mappings - self.__procs_by_physid_and_coreid = {} - self.__physid_and_coreid_by_proc = {} - - # Connect to the Windows Management Instrumentation (WMI) interface - wmiInstance = wmi.WMI() - - # Retrieve CPU information using WMI - for physicalId, processor in enumerate(wmiInstance.Win32_Processor()): - - threadPerCore = processor.NumberOfLogicalProcessors // processor.NumberOfCores - procId = 0 - - for coreId in range(processor.NumberOfCores): - for _ in range(threadPerCore): - self.__procs_by_physid_and_coreid.setdefault( - str(physicalId), {} - ).setdefault(str(coreId), set()).add(str(procId)) - self.__physid_and_coreid_by_proc[str(procId)] = ( - str(physicalId), - str(coreId), - ) - procId += 1 - - def getWindowsMemory(self): - """Gets information on system memory, Windows compatible version.""" - # From - # http://stackoverflow.com/questions/2017545/get-memory-usage-of-computer-in-windows-with-python + self.__threadid_by_cpuid_and_coreid = {} + self.__cpuid_and_coreid_by_threadid = {} + + for (cpu_id, physical_core_id, logical_core_id) in coreInfo: + self.__threadid_by_cpuid_and_coreid.setdefault( + str(cpu_id), {}).setdefault( + physical_core_id, set()).add(str(logical_core_id)) + self.__cpuid_and_coreid_by_threadid[logical_core_id] = (str(cpu_id), + str(physical_core_id)) + + def updateWindowsMemory(self): + """Updates the internal store of memory available for Windows.""" if not hasattr(self, '__windowsStat'): - class MEMORYSTATUSEX(ctypes.Structure): - """Represents Windows memory information.""" - _fields_ = [("dwLength", ctypes.c_uint), - ("dwMemoryLoad", ctypes.c_uint), - ("ullTotalPhys", ctypes.c_ulonglong), - ("ullAvailPhys", ctypes.c_ulonglong), - ("ullTotalPageFile", ctypes.c_ulonglong), - ("ullAvailPageFile", ctypes.c_ulonglong), - ("ullTotalVirtual", ctypes.c_ulonglong), - ("ullAvailVirtual", ctypes.c_ulonglong), - ("sullAvailExtendedVirtual", ctypes.c_ulonglong),] - - def __init__(self): - # have to initialize this to the size of MEMORYSTATUSEX - self.dwLength = 2*4 + 7*8 # size = 2 ints, 7 longs - super(MEMORYSTATUSEX, self).__init__() - - self.__windowsStat = MEMORYSTATUSEX() + self.__windowsStat = rqd.rqwinutils.MEMORYSTATUSEX() ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(self.__windowsStat)) - return self.__windowsStat + + disk_usage = psutil.disk_usage(self.getTempPath()) + + self.__renderHost.total_mcp = disk_usage.total // 1024 + self.__renderHost.free_mcp = disk_usage.free // 1024 + + stat = self.__windowsStat + + self.__renderHost.total_mem = int(stat.ullTotalPhys / 1024) + self.__renderHost.free_mem = int(stat.ullAvailPhys / 1024) + + self.__renderHost.total_swap = int(stat.ullTotalPageFile / 1024) + self.__renderHost.free_swap = int(stat.ullAvailPageFile / 1024) + + self.__renderHost.num_gpus = self.getGpuCount() + self.__renderHost.total_gpu_mem = self.getGpuMemoryTotal() + self.__renderHost.free_gpu_mem = self.getGpuMemoryFree() + + def updateLinuxMemory(self): + """Gets information on system memory for Linux.""" + # Reads dynamic information for mcp + mcpStat = os.statvfs(self.getTempPath()) + self.__renderHost.total_mcp = (mcpStat.f_blocks * mcpStat.f_frsize) // 1024 + self.__renderHost.free_mcp = (mcpStat.f_bavail * mcpStat.f_bsize) // 1024 + + # Reads dynamic information from /proc/meminfo + with open(rqd.rqconstants.PATH_MEMINFO, "r", encoding='utf-8') as fp: + for line in fp: + if line.startswith("MemFree"): + freeMem = int(line.split()[1]) + elif line.startswith("SwapFree"): + freeSwapMem = int(line.split()[1]) + elif line.startswith("SwapTotal"): + self.__renderHost.total_swap = int(line.split()[1]) + elif line.startswith("Cached"): + cachedMem = int(line.split()[1]) + elif line.startswith("MemTotal"): + self.__renderHost.total_mem = int(line.split()[1]) + + self.__renderHost.free_swap = freeSwapMem + self.__renderHost.free_mem = freeMem + cachedMem + self.__renderHost.num_gpus = self.getGpuCount() + self.__renderHost.total_gpu_mem = self.getGpuMemoryTotal() + self.__renderHost.free_gpu_mem = self.getGpuMemoryFree() + + self.__renderHost.attributes['swapout'] = self.__getSwapout() def updateMacMemory(self): """Updates the internal store of memory available, macOS compatible version.""" @@ -841,48 +850,22 @@ def updateMacMemory(self): else: self.__renderHost.free_swap = 0 + # Reads dynamic information for mcp + mcpStat = os.statvfs(self.getTempPath()) + self.__renderHost.total_mcp = (mcpStat.f_blocks * mcpStat.f_frsize) // KILOBYTE + self.__renderHost.free_mcp = (mcpStat.f_bavail * mcpStat.f_bsize) // KILOBYTE + def updateMachineStats(self): """Updates dynamic machine information during runtime""" + if platform.system() == "Linux": - # Reads dynamic information for mcp - mcpStat = os.statvfs(self.getTempPath()) - self.__renderHost.free_mcp = (mcpStat.f_bavail * mcpStat.f_bsize) // KILOBYTE - - # Reads dynamic information from /proc/meminfo - with open(rqd.rqconstants.PATH_MEMINFO, "r", encoding='utf-8') as fp: - for line in fp: - if line.startswith("MemFree"): - freeMem = int(line.split()[1]) - elif line.startswith("SwapFree"): - freeSwapMem = int(line.split()[1]) - elif line.startswith("Cached"): - cachedMem = int(line.split()[1]) - elif line.startswith("MemTotal"): - self.__renderHost.total_mem = int(line.split()[1]) - - self.__renderHost.free_swap = freeSwapMem - self.__renderHost.free_mem = freeMem + cachedMem - self.__renderHost.num_gpus = self.getGpuCount() - self.__renderHost.total_gpu_mem = self.getGpuMemoryTotal() - self.__renderHost.free_gpu_mem = self.getGpuMemoryFree() - - self.__renderHost.attributes['swapout'] = self.__getSwapout() + self.updateLinuxMemory() elif platform.system() == 'Darwin': self.updateMacMemory() - # Reads dynamic information for mcp - mcpStat = os.statvfs(self.getTempPath()) - self.__renderHost.free_mcp = (mcpStat.f_bavail * mcpStat.f_bsize) // KILOBYTE elif platform.system() == 'Windows': - TEMP_DEFAULT = 1048576 - stats = self.getWindowsMemory() - self.__renderHost.free_mcp = TEMP_DEFAULT - self.__renderHost.free_swap = int(stats.ullAvailPageFile / 1024) - self.__renderHost.free_mem = int(stats.ullAvailPhys / 1024) - self.__renderHost.num_gpus = self.getGpuCount() - self.__renderHost.total_gpu_mem = self.getGpuMemoryTotal() - self.__renderHost.free_gpu_mem = self.getGpuMemoryFree() + self.updateWindowsMemory() # Updates dynamic information self.__renderHost.load = self.getLoadAvg() @@ -923,10 +906,10 @@ def __enabledHT(self): def getHyperthreadingMultiplier(self): """ - Multiplied used to compute the number of threads that can be allocated simultaneously - on a core + Multiplier used to compute the number of threads that can be allocated simultaneously + on a core. This is a float as it can be fractional for hybrid cores. """ - return int(self.__renderHost.attributes['hyperthreadingMultiplier']) + return float(self.__renderHost.attributes.get('hyperthreadingMultiplier', 1.0)) def setupTaskset(self): """ Setup rqd for hyper-threading """ @@ -936,42 +919,52 @@ def setupGpu(self): """ Setup rqd for Gpus """ self.__gpusets = set(range(self.getGpuCount())) - def reserveHT(self, frameCores): + def reserveCores(self, coresCount=0, logical=True): """ Reserve cores for use by taskset taskset -c 0,1,8,9 COMMAND Not thread save, use with locking. - @type frameCores: int - @param frameCores: The total physical cores reserved by the frame. + @type coresCount: int + @param coresCount: The total physical cores reserved by the frame. + @type logical: bool + @param logical: If True, reserve logical cores (aka threads), + else reserve physical cores (legacy). + note: logical cores is what you see in htop or task manager. + For example, a 16 core CPU with hyper-threading will have 32 logical cores. @rtype: string @return: The cpu-list for taskset -c """ - if frameCores % 100: + if coresCount % 100: log.warning('Taskset: Can not reserveHT with fractional cores') return None - log.info('Taskset: Requesting reserve of %d', (frameCores // 100)) + log.info('Taskset: Requesting reserve of %d', (coresCount // 100)) # Look for the most idle physical cpu. # Prefer to assign cores from the same physical cpu. # Spread different frames around on different physical cpus. avail_cores = {} - avail_cores_count = 0 + avail_procs_count = 0 reserved_cores = self.__coreInfo.reserved_cores - for physid, cores in self.__procs_by_physid_and_coreid.items(): + for physid, cores in self.__threadid_by_cpuid_and_coreid.items(): for coreid in cores.keys(): if int(physid) in reserved_cores and \ int(coreid) in reserved_cores[int(physid)].coreid: continue avail_cores.setdefault(physid, set()).add(coreid) - avail_cores_count += 1 - - remaining_cores = frameCores / 100 - - if avail_cores_count < remaining_cores: - err = ('Not launching, insufficient hyperthreading cores to reserve ' - 'based on frameCores (%s < %s)') \ - % (avail_cores_count, remaining_cores) + if logical: + # Count all threads (logical cores) + avail_procs_count += len(cores[coreid]) + else: + # Count only physical cores + avail_procs_count += 1 + + query_procs = coresCount / 100 + + if avail_procs_count < query_procs: + err = ('Not launching, insufficient cores to reserve ' + 'based on coresCount (%s < %s)') \ + % (avail_procs_count, query_procs) log.critical(err) raise rqd.rqexceptions.CoreReservationFailureException(err) @@ -983,24 +976,54 @@ def reserveHT(self, frameCores): # the most idle cores first. key=lambda tup: len(tup[1]), reverse=True): - - while remaining_cores > 0 and len(cores) > 0: - coreid = cores.pop() - # Give all the hyperthreads on this core. - # This counts as one core. + cores = sorted(list(cores), key=int) + while query_procs > 0 and len(cores) > 0: + # Reserve hyper-threaded cores first (2 threads(logical cores) for 1 physical core) + # Avoid booking a hyper-threaded core for an odd thread count remainder + # ex: if query_procs==2, get the next core with 2 threads + # ex: if query_procs==1, get the next core with 1 thread or any other core + # here we fall back on the first physical core + # (assuming "first in list" == "has more threads") + # if we didn't find a core with the right number of threads, and continue the loop. + coreid = next(iter( + [cid for cid in cores + if len(self.__threadid_by_cpuid_and_coreid[physid][cid]) <= query_procs]), + cores[0]) + cores.remove(coreid) + procids = self.__threadid_by_cpuid_and_coreid[physid][coreid] reserved_cores[int(physid)].coreid.extend([int(coreid)]) - remaining_cores -= 1 - - for procid in self.__procs_by_physid_and_coreid[physid][coreid]: - tasksets.append(procid) - - if remaining_cores == 0: + if logical: + query_procs -= len(procids) + else: + query_procs -= 1 + tasksets.extend(procids) + + if query_procs <= 0: + # Could be negative if we reserved a full core with more threads than needed break log.warning('Taskset: Reserving procs - %s', ','.join(tasksets)) return ','.join(tasksets) + + def reserveHT(self, frameCores): + """ Reserve cores for use by taskset + taskset -c 0,1,8,9 COMMAND + Not thread save, use with locking. + @type frameCores: int + @param frameCores: The total physical cores reserved by the frame. + @rtype: string + @return: The cpu-list for taskset -c + """ + warnings.warn( + "The `reserveHT` method is deprecated and will be removed in a future release. " + "Use `reserveCores(logical=False)` instead.", + DeprecationWarning, + stacklevel=2 + ) + return self.reserveCores(frameCores, logical=False) + # pylint: disable=inconsistent-return-statements def releaseHT(self, reservedHT): """ Release cores used by taskset @@ -1017,7 +1040,7 @@ def releaseHT(self, reservedHT): # aren't valid core identities. reserved_cores = self.__coreInfo.reserved_cores for core in reservedHT.split(','): - physical_id_str, core_id_str = self.__physid_and_coreid_by_proc.get(core) + physical_id_str, core_id_str = self.__cpuid_and_coreid_by_threadid.get(core) physical_id = int(physical_id_str) core_id = int(core_id_str) diff --git a/rqd/rqd/rqwinutils.py b/rqd/rqd/rqwinutils.py new file mode 100644 index 000000000..6e843d96a --- /dev/null +++ b/rqd/rqd/rqwinutils.py @@ -0,0 +1,149 @@ +# pylint: disable=line-too-long +""" +This module provides functionality to retrieve and display information about the logical processors in a Windows system. +It uses Windows API calls to gather details about processor groups, their affinities, and the number of logical cores. +Classes: + GROUP_AFFINITY (Structure): Represents the affinity of a group of processors. + PROCESSOR_RELATIONSHIP (Structure): Represents information about affinity within a processor group. + DUMMYUNIONNAME (Union): A union of possible information to get about a processor. + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX (Structure): Contains information about the relationships of logical processors and related hardware. +Functions: + get_logical_processor_information_ex(): Retrieves information about all the logical processors in the system. + +Note: + This is tailored for the needs of OpenCue, especially for hybrid CPUs + TODO: Maybe we should contribute this back to psutils ? +""" +from ctypes import c_ulonglong, c_uint, Structure, Union, WinDLL +from ctypes import POINTER, sizeof, WinError, byref, get_last_error +from ctypes import wintypes + + +class GROUP_AFFINITY(Structure): + """ A structure that represents the affinity of a group of processors. + Attributes: + Mask (c_ulonglong): A bitmask that specifies the affinity of processors in the group. + Group (wintypes.WORD): The processor group number. + Reference: + https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-group_affinity + """ + _fields_ = [("Mask", c_ulonglong), + ("Group", wintypes.WORD), + ("Reserved", wintypes.WORD * 3)] + + +class PROCESSOR_RELATIONSHIP(Structure): + """ Represents information about affinity within a processor group. + Attributes: + Flags (BYTE): Flags that provide additional information about the processor. + EfficiencyClass (BYTE): The efficiency class of the processor. + GroupCount (WORD): The number of processor groups. + GroupMask (GROUP_AFFINITY * 1): The affinity mask for the processor group. + Reference: + - https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-processor_relationship + """ + _fields_ = [("Flags", wintypes.BYTE), + ("EfficiencyClass", wintypes.BYTE), + ("Reserved", wintypes.BYTE * 20), + ("GroupCount", wintypes.WORD), + ("GroupMask", GROUP_AFFINITY * 1)] + + +class DUMMYUNIONNAME(Union): + """ A union of possible information to get about a processor. + Here we only get the processor relationship. + Attributes: + Processor (PROCESSOR_RELATIONSHIP): Represents the processor relationship. + Reference: + - https://learn.microsoft.com/fr-fr/windows/win32/api/winnt/ns-winnt-system_logical_processor_information_ex + """ + _fields_ = [("Processor", PROCESSOR_RELATIONSHIP)] + + +class SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX(Structure): + """ Contains information about the relationships of logical processors and related hardware. + Attributes: + Relationship: The type of relationship between the logical processors. + Size: The size of the structure. + DUMMYUNIONNAME: see the class doc. + Reference: + - https://learn.microsoft.com/fr-fr/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex + """ + _fields_ = [("Relationship", wintypes.DWORD), + ("Size", wintypes.DWORD), + ("DUMMYUNIONNAME", DUMMYUNIONNAME)] + + +class MEMORYSTATUSEX(Structure): + """Represents Windows memory information.""" + # From + # http://stackoverflow.com/questions/2017545/get-memory-usage-of-computer-in-windows-with-python + _fields_ = [("dwLength", c_uint), + ("dwMemoryLoad", c_uint), + ("ullTotalPhys", c_ulonglong), + ("ullAvailPhys", c_ulonglong), + ("ullTotalPageFile", c_ulonglong), + ("ullAvailPageFile", c_ulonglong), + ("ullTotalVirtual", c_ulonglong), + ("ullAvailVirtual", c_ulonglong), + ("ullAvailExtendedVirtual", c_ulonglong), ] + + def __init__(self): + # have to initialize this to the size of MEMORYSTATUSEX + self.dwLength = 2 * 4 + 7 * 8 # size = 2 ints, 7 longs + super(MEMORYSTATUSEX, self).__init__() + + +def get_logical_processor_information_ex(): + """ Retrieves information about all the logical processors in the system. + Usage: + Used in rqmachine.Machine.__initStatsWindows() + Returns: + List of tuples for each thread (logical core): + - group (int): Its processor group ID. (we can't detect different CPUS directly) + - core_id (int): Its physical core ID. + - thread_id (int): Its logical core ID. + Raises: + WinError: If there is an error in retrieving the processor information. + References: + https://learn.microsoft.com/fr-fr/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex + """ + + kernel32 = WinDLL('kernel32', use_last_error=True) + GetLogicalProcessorInformationEx = kernel32.GetLogicalProcessorInformationEx + GetLogicalProcessorInformationEx.argtypes = [wintypes.DWORD, + POINTER(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX), + POINTER(wintypes.DWORD)] + GetLogicalProcessorInformationEx.restype = wintypes.BOOL + + RelationProcessorCore = 0 # RelationProcessorCore constant + ERROR_INSUFFICIENT_BUFFER = 122 + + # Get required buffer size by calling the function with a null buffer + buffer_size = wintypes.DWORD(0) + if not GetLogicalProcessorInformationEx(RelationProcessorCore, None, byref(buffer_size)): + if get_last_error() != ERROR_INSUFFICIENT_BUFFER: + raise WinError(get_last_error()) + + # Get information about all the logical processors + buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX * ( + buffer_size.value // sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)))() + if not GetLogicalProcessorInformationEx(RelationProcessorCore, buffer, byref(buffer_size)): + raise WinError(get_last_error()) + + # Extract information + cores_info = [] + core_id = 0 + _thread_id_inc = 0 + for item in buffer: + if item.Relationship == RelationProcessorCore: + mask = item.DUMMYUNIONNAME.Processor.GroupMask[0].Mask + group = item.DUMMYUNIONNAME.Processor.GroupMask[0].Group + logical_cores = bin(mask).count('1') + thread_ids = [_thread_id_inc + i for i in range(logical_cores)] + for thread_id in thread_ids: + cores_info.append((group, core_id, thread_id)) + _thread_id_inc += logical_cores + core_id += 1 + + return cores_info diff --git a/rqd/tests/cpuinfo/_cpuinfo_i9_12900_hybrid_ht_24-16-1-1.5 b/rqd/tests/cpuinfo/_cpuinfo_i9_12900_hybrid_ht_24-16-1-1.5 new file mode 100644 index 000000000..1862c4e90 --- /dev/null +++ b/rqd/tests/cpuinfo/_cpuinfo_i9_12900_hybrid_ht_24-16-1-1.5 @@ -0,0 +1,672 @@ +processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 1238.064 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 0 +cpu cores : 16 +apicid : 0 +initial apicid : 0 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 1 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 0 +cpu cores : 16 +apicid : 1 +initial apicid : 1 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 2 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 4 +cpu cores : 16 +apicid : 8 +initial apicid : 8 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 3 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 4 +cpu cores : 16 +apicid : 9 +initial apicid : 9 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 4 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 8 +cpu cores : 16 +apicid : 16 +initial apicid : 16 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 5 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 8 +cpu cores : 16 +apicid : 17 +initial apicid : 17 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 6 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 12 +cpu cores : 16 +apicid : 24 +initial apicid : 24 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 7 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 998.689 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 12 +cpu cores : 16 +apicid : 25 +initial apicid : 25 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 8 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 16 +cpu cores : 16 +apicid : 32 +initial apicid : 32 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 9 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 16 +cpu cores : 16 +apicid : 33 +initial apicid : 33 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 10 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 20 +cpu cores : 16 +apicid : 40 +initial apicid : 40 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 11 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 20 +cpu cores : 16 +apicid : 41 +initial apicid : 41 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 12 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2391.143 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 24 +cpu cores : 16 +apicid : 48 +initial apicid : 48 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 13 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 24 +cpu cores : 16 +apicid : 49 +initial apicid : 49 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 14 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2244.091 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 28 +cpu cores : 16 +apicid : 56 +initial apicid : 56 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 15 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 28 +cpu cores : 16 +apicid : 57 +initial apicid : 57 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 16 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 32 +cpu cores : 16 +apicid : 64 +initial apicid : 64 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 17 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 33 +cpu cores : 16 +apicid : 66 +initial apicid : 66 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 18 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 34 +cpu cores : 16 +apicid : 68 +initial apicid : 68 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 19 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 35 +cpu cores : 16 +apicid : 70 +initial apicid : 70 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 20 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 36 +cpu cores : 16 +apicid : 72 +initial apicid : 72 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 21 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 37 +cpu cores : 16 +apicid : 74 +initial apicid : 74 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 22 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 38 +cpu cores : 16 +apicid : 76 +initial apicid : 76 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + +processor : 23 +vendor_id : GenuineIntel +cpu family : 6 +model : 151 +model name : 12th Gen Intel(R) Core(TM) i9-12900 +stepping : 2 +microcode : 0x22 +cpu MHz : 2400.000 +cache size : 30720 KB +physical id : 0 +siblings : 24 +core id : 39 +cpu cores : 16 +apicid : 78 +initial apicid : 78 +fpu : yes +fpu_exception : yes +cpuid level : 32 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr flush_l1d arch_capabilities +vmx flags : vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple shadow_vmcs ept_mode_based_exec tsc_scaling usr_wait_pause +bugs : spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb +bogomips : 4838.40 +clflush size : 64 +cache_alignment : 64 +address sizes : 46 bits physical, 48 bits virtual +power management: + diff --git a/rqd/tests/cpuinfo/_cpuinfo_shark_ht_8-4-2-2 b/rqd/tests/cpuinfo/_cpuinfo_shark_ht_16-4-2-2 similarity index 100% rename from rqd/tests/cpuinfo/_cpuinfo_shark_ht_8-4-2-2 rename to rqd/tests/cpuinfo/_cpuinfo_shark_ht_16-4-2-2 diff --git a/rqd/tests/cpuinfo/_cpuinfo_srdsvr05_ht_12-6-2-2 b/rqd/tests/cpuinfo/_cpuinfo_srdsvr05_ht_24-6-2-2 similarity index 100% rename from rqd/tests/cpuinfo/_cpuinfo_srdsvr05_ht_12-6-2-2 rename to rqd/tests/cpuinfo/_cpuinfo_srdsvr05_ht_24-6-2-2 diff --git a/rqd/tests/test_rqmachine.py b/rqd/tests/test_rqmachine.py index 974818ef9..8397080e7 100644 --- a/rqd/tests/test_rqmachine.py +++ b/rqd/tests/test_rqmachine.py @@ -334,6 +334,7 @@ def test_multipleGpus(self): self.assertEqual(122701222, self.machine.getGpuMemoryFree()) def test_getPathEnv(self): + rqd.rqconstants.RQD_USE_PATH_ENV_VAR = False self.assertEqual( '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', self.machine.getPathEnv()) @@ -418,7 +419,7 @@ def test_reserveHT(self): step5 - taskset4: 3 remaining, Reserve 3 cores (ph0+ph1) step5 - taskset5: No more cores """ - cpuInfo = os.path.join(os.path.dirname(__file__), 'cpuinfo', '_cpuinfo_shark_ht_8-4-2-2') + cpuInfo = os.path.join(os.path.dirname(__file__), 'cpuinfo', '_cpuinfo_shark_ht_16-4-2-2') self.fs.add_real_file(cpuInfo) self.machine.testInitMachineStats(cpuInfo) @@ -485,6 +486,261 @@ def assertTaskSet(taskset_list): with self.assertRaises(rqd.rqexceptions.CoreReservationFailureException): tasksets4 = self.machine.reserveHT(300) + def test_reserveCores(self): + """ + Total 2 physical(ph) processors with 4 cores each with 2 threads each (total 16 threads) + note: reserving odd threads will result in even threads when there is no mono-thread cores + step1 - taskset0: Reserve 4 threads (2 cores) (ph0->0,1) + step2 - taskset1: Reserve 6 threads (3 cores) (ph1->0,1,2) + step3 - Release cores on taskset0 (ph0->0,1) + step4 - taskset3: Reserve 6 threads (3 cores) (ph0->0,1,2) + step5 - taskset4: 4 remaining, Reserve 4 threads (2 cores) (ph0->3 + ph1->3) + step6 - taskset5: No more cores + """ + cpuInfo = os.path.join(os.path.dirname(__file__), 'cpuinfo', '_cpuinfo_shark_ht_16-4-2-2') + self.fs.add_real_file(cpuInfo) + self.machine.testInitMachineStats(cpuInfo) + + self.machine.setupTaskset() + + # ------------------------step1------------------------- + # phys_id 0 + # - core_id 0 + # - process_id 0 + # - process_id 8 + # - core_id 1 + # - process_id 1 + # - process_id 9 + tasksets0 = self.machine.reserveCores(400, logical=True) + # pylint: disable=no-member + self.assertCountEqual(['0', '8', '1', '9'], + sorted(tasksets0.split(','))) + + # ------------------------step2------------------------- + # phys_id 1 + # - core_id 0 + # - process_id 4 + # - process_id 12 + # - core_id 1 + # - process_id 5 + # - process_id 13 + # - core_id 2 + # - process_id 6 + # - process_id 14 + tasksets1 = self.machine.reserveCores(600, logical=True) + # pylint: disable=no-member + self.assertCountEqual(['4', '12', '5', '13', '6', '14'], + sorted(tasksets1.split(','))) + + # reserved cores got updated properly + # pylint: disable=no-member + self.assertCountEqual([0, 1], self.coreDetail.reserved_cores[0].coreid) + + # Make sure tastsets don't overlap + self.assertTrue(set(tasksets0.split(',')).isdisjoint(tasksets1.split(','))) + + # ------------------------step3------------------------- + # Releasing a physcore shouldn't impact other physcores + self.machine.releaseHT(tasksets0) + # pylint: disable=no-member + self.assertTrue(1 in self.coreDetail.reserved_cores) + # pylint: disable=no-member + self.assertCountEqual([0, 1, 2], self.coreDetail.reserved_cores[1].coreid) + + # ------------------------step4------------------------- + # phys_id 0 + # - core_id 0 + # - process_id 0 + # - process_id 8 + # - core_id 1 + # - process_id 1 + # - process_id 9 + # - core_id 2 + # - process_id 2 + # - process_id 10 + tasksets3 = self.machine.reserveCores(600, logical=True) + # pylint: disable=no-member + self.assertCountEqual(['0', '8', '1', '9', '2', '10'], sorted(tasksets3.split(','))) + + # ------------------------step5------------------------- + # phys_id 0 + # - core_id 3 + # - process_id 3 + # - process_id 11 + # phys_id 1 + # - core_id 3 + # - process_id 7 + # - process_id 15 + tasksets4 = self.machine.reserveCores(400, logical=True) + # pylint: disable=no-member + self.assertCountEqual(['3', '11', '7', '15'], sorted(tasksets4.split(','))) + + # ------------------------step6------------------------- + # No cores available + with self.assertRaises(rqd.rqexceptions.CoreReservationFailureException): + self.machine.reserveCores(200, logical=True) + + def test_reserveHybridHT(self): + """ + Total 1 physical(ph) processors with 8 P-cores(2 threads) and 8 E-cores(1 thread), + for a total of 24 threads. + note: reserving odd threads will result in even threads when there is no mono-thread cores, + which is not the case here. it should reserve E-cores to match the odd request. + step1 - taskset0: Reserve 4 threads (2P), 4 threads occupied + step2 - taskset1: Reserve 5 threads (2P, 1E), 9 threads occupied + step3 - taskset2: Reserve 6 threads (3P), 15 threads occupied + step4 - Release taskset0, 3P and 7E remaining, 11 threads occupied + step5 - taskset3: Reserve 12 threads (3P, 6E), 23 threads occupied + step6 - taskset4: Reserve 1 thread (1E), 24 threads occupied + step7 - Reserve 1 thread (1E), no more free cores + """ + cpuInfo = os.path.join(os.path.dirname(__file__), + 'cpuinfo', + '_cpuinfo_i9_12900_hybrid_ht_24-16-1-1.5') + self.fs.add_real_file(cpuInfo) + self.machine.testInitMachineStats(cpuInfo) + + self.machine.setupTaskset() + + # ------------------------step1------------------------- + # phys_id 0 + # - P core_id 0 + # - process_id 0 + # - process_id 1 + # - P core_id 4 + # - process_id 2 + # - process_id 3 + # - P core_id 8 + # - process_id 4 + # - process_id 5 + # - P core_id 12 + # - process_id 6 + # - process_id 7 + # - P core_id 16 + # - process_id 8 + # - process_id 9 + # - P core_id 20 + # - process_id 10 + # - process_id 11 + # - P core_id 24 + # - process_id 12 + # - process_id 13 + # - P core_id 28 + # - process_id 14 + # - process_id 15 + + # - E core_id 32 + # - process_id 16 + # - E core_id 33 + # - process_id 17 + # - E core_id 34 + # - process_id 18 + # - E core_id 35 + # - process_id 19 + # - E core_id 36 + # - process_id 20 + # - E core_id 37 + # - process_id 21 + # - E core_id 38 + # - process_id 22 + # - E core_id 39 + # - process_id 23 + tasksets0 = self.machine.reserveCores(400, logical=True) + + # should reserve 2P (0,1, 2,3) + # pylint: disable=no-member + self.assertCountEqual(['0', '1', '2', '3'], tasksets0.split(',')) + + # should have 2 cores occupied + # pylint: disable=no-member + self.assertCountEqual([0, 4], self.coreDetail.reserved_cores[0].coreid) + # should have 4 threads occupied + self.assertEqual(len(tasksets0.split(',')), 4) + + + # ------------------------step2------------------------- + tasksets1 = self.machine.reserveCores(500, logical=True) + + # should reserve 2P + 1E (4,5, 6,7, 16) + # pylint: disable=no-member + self.assertCountEqual(['4', '5', '6', '7', '16'], tasksets1.split(',')) + + # should have 5 cores occupied + # pylint: disable=no-member + self.assertCountEqual([0, 4, 8, 12, 32], self.coreDetail.reserved_cores[0].coreid) + # should have 9 threads occupied + self.assertEqual(len(tasksets0.split(',')) + + len(tasksets1.split(',')), + 9) + + + # ------------------------step3------------------------- + tasksets2 = self.machine.reserveCores(600, logical=True) + + # should reserve 3P (8,9, 10,11, 12,13) + # pylint: disable=no-member + self.assertCountEqual(['8', '9', '10', '11', '12', '13'], tasksets2.split(',')) + + # should have 8 cores occupied + # pylint: disable=no-member + self.assertCountEqual([0, 4, 8, 12, 16, 20, 24, 32], + self.coreDetail.reserved_cores[0].coreid) + # should have 15 threads occupied + self.assertEqual(len(tasksets0.split(',')) + + len(tasksets1.split(',')) + + len(tasksets2.split(',')), + 15) + + + # ------------------------step4------------------------- + self.machine.releaseHT(tasksets0) + # should release 2P (0,1, 2,3) + # should have 6 cores occupied + # pylint: disable=no-member + self.assertCountEqual([8, 12, 16, 20, 24, 32], self.coreDetail.reserved_cores[0].coreid) + # should have 11 threads occupied + self.assertEqual(len(tasksets1.split(',')) + + len(tasksets2.split(',')), + 11) + + + # ------------------------step5------------------------- + tasksets3 = self.machine.reserveCores(1200, logical=True) + + # should reserve 3P + 6E (0,1, 2,3, 14,15, 17, 18, 19, 20, 21, 22) + # pylint: disable=no-member + self.assertCountEqual(['0', '1', '2', '3', '14', '15', '17', '18', '19', '20', '21', '22'], + tasksets3.split(',')) + + # should have 15 cores occupied, 1E free + # pylint: disable=no-member + self.assertCountEqual([0, 4, 8, 12, 16, 20, 24, 28, 32, 33, 34, 35, 36, 37, 38], + self.coreDetail.reserved_cores[0].coreid) + + # should have 23 threads occupied + self.assertEqual(len(tasksets1.split(',')) + + len(tasksets2.split(',')) + + len(tasksets3.split(',')), + 23) + + # ------------------------step6------------------------- + tasksets4 = self.machine.reserveCores(100, logical=True) + + # should reserve 1E (23) + # pylint: disable=no-member + self.assertCountEqual(['23'], tasksets4.split(',')) + + # Make sure 24 threads are occupied + self.assertEqual(len(tasksets1.split(',')) + + len(tasksets2.split(',')) + + len(tasksets3.split(',')) + + len(tasksets4.split(',')), + 24) + + # ------------------------step7------------------------- + # No cores available + with self.assertRaises(rqd.rqexceptions.CoreReservationFailureException): + self.machine.reserveCores(100, logical=True) def test_tags(self): tags = ["test1", "test2", "test3"] @@ -509,7 +765,7 @@ def setUp(self): self.rqd = rqd.rqcore.RqCore() def test_shark(self): - self.__cpuinfoTestHelper('_cpuinfo_shark_ht_8-4-2-2') + self.__cpuinfoTestHelper('_cpuinfo_shark_ht_16-4-2-2') def test_shark_ht(self): self.__cpuinfoTestHelper('_cpuinfo_shark_8-4-2') @@ -533,28 +789,37 @@ def test_8600(self): self.__cpuinfoTestHelper('_cpuinfo_hp8600_8-4-2') def test_srdsvr05(self): - self.__cpuinfoTestHelper('_cpuinfo_srdsvr05_ht_12-6-2-2') + self.__cpuinfoTestHelper('_cpuinfo_srdsvr05_ht_24-6-2-2') def test_srdsvr09(self): self.__cpuinfoTestHelper('_cpuinfo_srdsvr09_48-12-4') + def test_i9_12900(self): + self.__cpuinfoTestHelper('_cpuinfo_i9_12900_hybrid_ht_24-16-1-1.5') + def __cpuinfoTestHelper(self, pathCpuInfo): - # File format: _cpuinfo_dub_x-x-x where x-x-x is totalCores-coresPerProc-numProcs + # File format: _cpuinfo_dub_x-x-x where x-x-x is totalThreads-coresPerProc-numProcs pathCpuInfo = os.path.join(os.path.dirname(__file__), 'cpuinfo', pathCpuInfo) self.meminfo.set_contents(MEMINFO_MODERATE_USAGE) renderHost, coreInfo = self.rqd.machine.testInitMachineStats(pathCpuInfo) - totalCores, coresPerProc, numProcs = pathCpuInfo.split('_')[-1].split('-')[:3] + totalThreads, coresPerProc, numProcs = map(int, pathCpuInfo.split('_')[-1].split('-')[:3]) + threadsPerProc = totalThreads // numProcs + ht_multiplier = float(pathCpuInfo.split('-')[3]) if '_ht_' in pathCpuInfo else 1.0 + totalCores = totalThreads // ht_multiplier + self.assertEqual(float(renderHost.attributes.get('hyperthreadingMultiplier', 1.0)), + ht_multiplier) + self.assertEqual(coresPerProc * numProcs, + totalThreads // ht_multiplier) # pylint: disable=no-member - self.assertEqual(renderHost.num_procs, int(numProcs)) - self.assertEqual(renderHost.cores_per_proc, int(coresPerProc) * 100) - self.assertEqual(coreInfo.total_cores, int(totalCores) * 100) - self.assertEqual(coreInfo.idle_cores, int(totalCores) * 100) + self.assertEqual(renderHost.num_procs, numProcs) + self.assertEqual(coreInfo.total_cores, totalCores * 100) + self.assertEqual(coreInfo.total_threads, totalThreads * 100) + self.assertEqual(renderHost.cores_per_proc, coresPerProc * 100) + self.assertEqual(renderHost.threads_per_proc, threadsPerProc * 100) + self.assertEqual(coreInfo.idle_cores, totalCores * 100) self.assertEqual(coreInfo.locked_cores, 0) self.assertEqual(coreInfo.booked_cores, 0) - if '_ht_' in pathCpuInfo: - self.assertEqual( - renderHost.attributes['hyperthreadingMultiplier'], pathCpuInfo.split('-')[3]) @mock.patch('platform.system', new=mock.MagicMock(return_value='Darwin')) diff --git a/rust/crates/rqd/src/system/linux.rs b/rust/crates/rqd/src/system/linux.rs index 28cca98c5..5bbcea39a 100644 --- a/rust/crates/rqd/src/system/linux.rs +++ b/rust/crates/rqd/src/system/linux.rs @@ -63,6 +63,7 @@ pub struct ProcessorInfoData { hyperthreading_multiplier: u32, num_sockets: u32, cores_per_socket: u32, + threads_per_proc: u32, pub processor_structure: ProcessorStructure, } @@ -80,6 +81,7 @@ struct MachineStaticInfo { /// Number of sockets (also know as physical cores) pub num_sockets: u32, pub cores_per_socket: u32, + pub threads_per_proc: u32, // Unlike the python counterpart, the multiplier is not automatically applied to total_procs pub hyperthreading_multiplier: u32, pub boot_time_secs: u64, @@ -152,6 +154,7 @@ impl LinuxSystem { total_swap, num_sockets: cpu_initial_info.num_sockets, cores_per_socket: cpu_initial_info.cores_per_socket, + threads_per_proc: cpu_initial_info.threads_per_proc, hyperthreading_multiplier: cpu_initial_info.hyperthreading_multiplier, boot_time_secs: Self::read_boot_time(&config.proc_stat_path).unwrap_or(0), tags: Self::setup_tags(config), @@ -295,6 +298,7 @@ impl LinuxSystem { hyperthreading_multiplier: hyper_modifier, num_sockets, cores_per_socket: num_threads / num_sockets, + threads_per_proc: num_threads / num_sockets, processor_structure, }) } @@ -748,6 +752,7 @@ impl SystemManager for LinuxSystem { total_swap: self.static_info.total_swap, num_sockets: self.static_info.num_sockets, cores_per_socket: self.static_info.cores_per_socket, + threads_per_proc: self.static_info.threads_per_proc, boot_time: self.static_info.boot_time_secs as u32, tags: self.static_info.tags.clone(), available_memory: dinamic_stat.available_memory, @@ -1412,6 +1417,7 @@ mod tests { total_swap: 0, num_sockets: physical_cpus, cores_per_socket: cores_per_cpu, + threads_per_proc: threads_per_core, hyperthreading_multiplier: 1, boot_time_secs: 0, tags: vec![], diff --git a/rust/crates/rqd/src/system/machine.rs b/rust/crates/rqd/src/system/machine.rs index 8b646625f..c4aac4138 100644 --- a/rust/crates/rqd/src/system/machine.rs +++ b/rust/crates/rqd/src/system/machine.rs @@ -450,6 +450,7 @@ impl MachineMonitor { facility: config.facility.clone(), num_procs: stats.num_sockets as i32, cores_per_proc: (stats.cores_per_socket * config.core_multiplier) as i32, + threads_per_proc: stats.threads_per_proc as i32, total_swap: (stats.total_swap / KIB) as i64, total_mem: (stats.total_memory / KIB) as i64, total_mcp: (stats.total_temp_storage / KIB) as i64, diff --git a/rust/crates/rqd/src/system/manager.rs b/rust/crates/rqd/src/system/manager.rs index 23087dbc6..8e3cc75ac 100644 --- a/rust/crates/rqd/src/system/manager.rs +++ b/rust/crates/rqd/src/system/manager.rs @@ -74,6 +74,8 @@ pub struct MachineStat { pub num_sockets: u32, /// Number of cores per processor unit pub cores_per_socket: u32, + // Number of threads per processor unit + pub threads_per_proc: u32, /// Timestamp for when the machine was booted up pub boot_time: u32, /// List of tags associated with this machine diff --git a/rust/crates/rqd/src/system/reservation.rs b/rust/crates/rqd/src/system/reservation.rs index a5957ef08..649d5bb43 100644 --- a/rust/crates/rqd/src/system/reservation.rs +++ b/rust/crates/rqd/src/system/reservation.rs @@ -40,6 +40,10 @@ impl ProcessorStructure { pub fn num_cores(&self) -> u32 { self.threads_by_core_unique_id.len() as u32 } + + pub fn num_threads(&self) -> u32 { + self.thread_id_lookup_table.len() as u32 + } } #[derive(Debug, Clone)] @@ -353,6 +357,7 @@ impl CoreStateManager { pub fn get_core_info_report(&self, core_multiplier: u32) -> CoreDetail { let total_cores = self.processor_structure.num_cores() as i32; let locked_cores = self.locked_cores as i32; + let total_threads = self.processor_structure.num_threads() as i32; // Idle cores needs to take both cores that are booked and locked. // At the end, the number of idle cores is the min between non_booked and unlocked cores @@ -370,6 +375,7 @@ impl CoreStateManager { .sum::(); CoreDetail { + total_threads, total_cores: total_cores * core_multiplier as i32, idle_cores: idle_cores * core_multiplier as i32, locked_cores: locked_cores * core_multiplier as i32, @@ -450,6 +456,12 @@ mod tests { assert_eq!(processor_structure.num_cores(), 4); } + #[test] + fn test_processor_structure_num_threads() { + let processor_structure = create_test_processor_structure(); + assert_eq!(processor_structure.num_threads(), 8); + } + #[test] fn test_core_booking_new() { let booking = CoreBooking::new();