Source code for monitormetrics.utils.processorspecific

"""This file contains processor specific information like model names, families and perf events"""

import re
import yaml

try:
    import importlib.resources as pkg_resources
except ImportError:
    import importlib_resources as pkg_resources


from monitormetrics.utils.exceptions import ProcessorVendorNotFoundError, KeyNotFoundError, \
    PerfEventListNotFoundError
from monitormetrics import perfevents


[docs]def cpu_micro_architecture_name(vendor_name, model_id, family_id): """ This function gives the name of the micro architecture based on CPU model and family IDs Args: vendor_name (str): Name of the vendor model_id : Model ID of the CPU family_id : Family ID of the cpu Returns: str: Name of the micro architecture Raises: ProcessorVendorNotFoundError: An error occurred while looking for processor vendor. KeyNotFoundError: An error occurred while looking for micro architecture """ # Micro architecture names is a dict with tuple (CPU family, model) as key # name of the micro architecture as value if vendor_name == "GenuineIntel": # source https://en.wikichip.org/wiki/intel/cpuid micro_architecture_names = { # Family 15 (15, 6): "Netburst", (15, 4): "Netburst", (15, 3): "Netburst", (15, 2): "Netburst", (15, 1): "Netburst", # Family 11 (11, 0): "KnightsFerry", (11, 1): "KnightsCorner", # Family 6 (big cores - client) (6, 151): "AlderLake", (6, 154): "AlderLake", (6, 167): "RocketLake", (6, 141): "TigerLake", (6, 140): "TigerLake", (6, 126): "IceLake", (6, 125): "IceLake", (6, 165): "CometLake", (6, 102): "CannonLake", (6, 158): "SkyLake", (6, 142): "SkyLake", (6, 94): "SkyLake", (6, 78): "SkyLake", (6, 71): "Broadwell", (6, 61): "Broadwell", (6, 70): "Haswell", (6, 69): "Haswell", (6, 60): "Haswell", (6, 58): "IvyBridge", (6, 42): "SandyBridge", (6, 37): "Westmere", (6, 31): "Nehalem", # Family 6 (big cores - server) (6, 143): "SapphireRapids", (6, 108): "IceLake", (6, 106): "IceLake", (6, 85): "SkyLake", (6, 79): "Broadwell", (6, 86): "Broadwell", (6, 63): "Haswell", (6, 62): "IvyBridge", (6, 45): "SandyBridge", (6, 44): "Westmere", (6, 47): "Westmere", (6, 46): "Nehalem", (6, 30): "Nehalem", (6, 26): "Nehalem", } elif vendor_name == "AuthenticAMD": # source https://en.wikichip.org/wiki/amd/cpuid micro_architecture_names = { # Family 25 (19h) (25, 1): "Zen3", (25, 33): "Zen3", (25, 64): "Zen3", (25, 80): "Zen3", # Family 23 (17h) (23, 144): "Zen2", (23, 113): "Zen2", (23, 104): "Zen2", (23, 96): "Zen2", (23, 71): "Zen2", (23, 49): "Zen2", (23, 49): "Zen+", (23, 8): "Zen+", (23, 32): "Zen", (23, 24): "Zen", (23, 17): "Zen", (23, 1): "Zen", (23, 32): "Zen", } elif vendor_name == "IBM": micro_architecture_names = { ('1.0 (pvr 004c 0100)', 'POWER8NVL, altivec supported'): "POWER8", } else: raise ProcessorVendorNotFoundError("Vendor {} not implemented".format(vendor_name)) try: micro_architecture_found = micro_architecture_names[(family_id, model_id)] except KeyError: raise KeyNotFoundError("Micro architecture not found in implemented list") from KeyError return micro_architecture_found
[docs]def llc_cache_miss_perf_event(processor_vendor, micro_architecture): """ This function gives the event code and umask for LLC cache miss event for different architectures Args: processor_vendor (str): Vendor of the processor micro_architecture (str): Name of the micro architecture of the processor Returns: str: String containing event code and umask Raises: ProcessorVendorNotFoundError: An error occurred while looking for processor vendor. """ # Here we will measure the "read" bandwidth from LLC to DRAM using offcore requests. They # measure core originated requests. Thus they cannot provide any "write" requests # More info can be found on this SOF thread: https://stackoverflow.com/questions/47612854/ # can-the-intel-performance-monitor-counters-be-used-to-measure-memory-bandwidth/47816066 # There is nice piece of work from these guys: https://www.readex.eu/wp-content/uploads/2017/06/ # ICPE2017_authors_version.pdf # There are two events OFFCORE_RESPONSE_0 and OFFCORE_RESPONSE_1. We can use them to measure # two events simultaneoulsy. Here we measure L3_MISS_LOCAL_DRAM with OFFCORE_RESPONSE_0 and # L3_MISS_REMOTE_DRAM with OFFCORE_RESPONSE_1 # These events are obtained using libpmf4 for different Intel micro architectures. # Still need some research for AMD processors. # Another method is to look at uncore cas_count_read/write events. Typically, they need root # access to measure them. # I will use the OFFCORE_RESPONSES for the time being and I need to stop digging into these # rabbit hole details. if processor_vendor == "GenuineIntel": # These are for OFFCORE responses if micro_architecture in ["Broadwell"]: llc_miss_event = "cpu/config=0x5301b7,config1=0x3f84008fff,name=LLC_MISS_LOCAL/u," \ "cpu/config=0x5301bb,config1=0x3fb8008fff,name=LLC_MISS_REMOTE/u" elif micro_architecture in ["SkyLake"]: llc_miss_event = "cpu/config=0x5301b7,config1=0x3f840085b7,name=LLC_MISS_LOCAL/u," \ "cpu/config=0x5301bb,config1=0x3f900085b7,name=LLC_MISS_REMOTE/u" elif micro_architecture in ["Haswell"]: llc_miss_event = "cpu/config=0x5301b7,config1=0x3f80408fff,name=LLC_MISS_LOCAL/u," \ "cpu/config=0x5301bb,config1=0x3fb8008fff,name=LLC_MISS_REMOTE/u" elif micro_architecture in ["SandyBridge"]: llc_miss_event = "cpu/config=0x5301b7,config1=0x3f80408fff,name=LLC_MISS_LOCAL/u," \ "cpu/config=0x5301bb,config1=0x3fff808fff,name=LLC_MISS_REMOTE/u" elif micro_architecture in ["Westmere"]: llc_miss_event = "cpu/config=0x5301b7,config1=0x10ff,name=LLC_MISS_LOCAL/u," \ "cpu/config=0x5301bb,config1=0x20ff,name=LLC_MISS_REMOTE/u" else: llc_miss_event = "" # if micro_architecture in ["Nehalem", "Westmere"]: # llc_miss_event = "cpu/event=0x09,umask=0x03,name=LLC-load-misses/u" # elif micro_architecture in ["IvyBridge", "Haswell", "Broadwell", "SkyLake"]: # llc_miss_event = "cpu/event=0xD1,umask=0x20,name=LLC-load-misses/u" # else: # llc_miss_event = "LLC-load-misses" elif processor_vendor == "AuthenticAMD": # if micro_architecture in ["Zen2", "Zen+", "Zen"]: # llc_miss_event = "cpu/event=0x06,umask=0x01,name=LLC-load-misses/u" # elif micro_architecture in ["Zen3"]: # llc_miss_event = "cpu/event=0x04,umask=0x01,name=LLC-load-misses/u" # else: # llc_miss_event = "" # On AMD we dont have OFFCORE_RESPONSE events and available events are uncore and they # need root access llc_miss_event = "" else: raise ProcessorVendorNotFoundError("Vendor {} not implemented".format(processor_vendor)) return llc_miss_event
[docs]def perf_event_list(micro_architecture): """ This function returns list of perf events implemented for a given processor and micro architecture Args: micro_architecture (str): Name of the micro architecture Returns: dict: A dict with name and event code of perf events dict: A dict with derived perf metrics and its formula """ perf_event_file = "{}.yml".format(micro_architecture) # Load perf event list file try: with pkg_resources.path(perfevents, perf_event_file) as evnt_file: with open(evnt_file, 'r') as yam: perf_event_dict = yaml.full_load(yam) except Exception: raise PerfEventListNotFoundError("Perf event list for {} not found". format(micro_architecture)) found_perf_events = {} derived_perf_metrics = {} for group, event_dict in perf_event_dict.items(): found_perf_events[group] = {} for event in event_dict['events']: if group in ["hardware_events", "software_events"]: get_name = event else: get_name = re.search(r"cpu/event=(.*),umask=(.*),name=(.*)/u", event).group(3) found_perf_events[group][get_name] = event if "formulae" in event_dict.keys(): derived_perf_metrics[group] = event_dict['formulae'] return found_perf_events, derived_perf_metrics
if __name__ == '__main__': name = cpu_micro_architecture_name('IBM', 'POWER8NVL, altivec supported', '1.0 (pvr 004c 0100)') print(name) a, b = perf_event_list(name) print(a, b)