"""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)