From 4563ef4749689cfb0e59938e8f18670c43f867f9 Mon Sep 17 00:00:00 2001 From: Arfouy <yussef.arfu@nure.ua> Date: Mon, 6 Mar 2023 14:10:58 +0100 Subject: [PATCH] code rapl v0 --- main.py | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rapl.py | 52 ++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 main.py create mode 100644 rapl.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..2112eb2 --- /dev/null +++ b/main.py @@ -0,0 +1,160 @@ +import math +import os +import sched +import string +import sys +import time +import types +import ctypes + +from cpuid import * +from msr import * +from ctypes.util import find_library + +# rapl msr availability +MSR_SUPPORT_MASK = 0xff +msr_support_table = None + +# Global Variables +num_nodes = 0 +num_core_threads = 0 # number of physical threads per core +num_pkg_threads = 0 # number of physical threads per package +num_pkg_cores = 0 # number of cores per package +os_cpu_count = 0 # number of OS CPUs + +os_map = None +pkg_map = None + +# Pre-computed variables used for time-window calculation +LN2 = 0.69314718055994530941723212145817656807550013436025 +A_F = [1.0, 1.1, 1.2, 1.3] +A_LNF = [ + 0.0000000000000000000000000000000000000000000000000000000, + 0.0953101798043249348602046211453853175044059753417968750, + 0.1823215567939545922460098381634452380239963531494140625, + 0.2623642644674910595625760834082029759883880615234375000] +class rapl_unit_multiplier_t: + def __init__(self): + self.power = 0.0 + self.energy = 0.0 + self.time = 0.0 + +class rapl_power_limit_control_t: + def __init__(self): + self.power_limit_watts = 0.0 + self.limit_time_window_seconds = 0.0 + self.limit_enabled = 0 + self.clamp_enabled = 0 + self.lock_enabled = 0 + +class rapl_parameters_t: + def __init__(self): + self.thermal_spec_power_watts = 0.0 + self.minimum_power_watts = 0.0 + self.maximum_power_watts = 0.0 + self.maximum_limit_time_window_seconds = 0.0 +# Define constants and types +MY_ERROR = -1 +size_t = ctypes.c_size_t +cpu_set_t = ctypes.c_uint64 * ((os.cpu_count() + 63) // 64) + +# Load necessary libraries +libc_path = find_library('c') +libc = ctypes.CDLL(libc_path, use_errno=True) + +def bind_context(new_context, old_context): + error = 0 + + ret = 0 + + if old_context is not None: + old_context_size = size_t(ctypes.sizeof(cpu_set_t)) + error = libc.sched_getaffinity(0, old_context_size, old_context) + + if error != 0: + + ret = MY_ERROR + + new_context_size = size_t(ctypes.sizeof(cpu_set_t)) + error += libc.sched_setaffinity(0, new_context_size, new_context) + + if error != 0: + + ret = MY_ERROR + + return ret + +def bind_cpu(cpu, old_context): + error = 0 + + cpu_context = cpu_set_t() + + libc.CPU_ZERO(ctypes.byref(cpu_context)) + libc.CPU_SET(cpu, ctypes.byref(cpu_context)) + error += bind_context(ctypes.byref(cpu_context), old_context) + + return error + +def parse_apic_id(info_l0, info_l1): + # Get the SMT ID + smt_mask_width = info_l0.eax & 0x1f + smt_mask = ~((-1) << smt_mask_width) + smt_id = info_l0.edx & smt_mask + + # Get the core ID + core_mask_width = info_l1.eax & 0x1f + core_mask = (~((-1) << core_mask_width)) ^ smt_mask + core_id = (info_l1.edx & core_mask) >> smt_mask_width + + # Get the package ID + pkg_mask = (-1) << core_mask_width + pkg_id = (info_l1.edx & pkg_mask) >> core_mask_width + + return {"smt_id": smt_id, "core_id": core_id, "pkg_id": pkg_id} + +def build_topology(): + global os_map, pkg_map, num_nodes, num_pkg_cores, num_pkg_threads, num_core_threads, os_cpu_count + + error = 0 + max_pkg = 0 + os_cpu_count = os.cpu_count() + os_map = [None] * os_cpu_count + + # Construct an os map: os_map[APIC_ID ... APIC_ID] + for i in range(os_cpu_count): + prev_context = cpu_set_t() + error = bind_cpu(i, prev_context) + + info_l0 = get_processor_topology(0) + info_l1 = get_processor_topology(1) + + os_map[i] = APIC_ID_t() + os_map[i].os_id = i + parse_apic_id(info_l0, info_l1, os_map[i]) + + num_core_threads = info_l0.ebx & 0xffff + num_pkg_threads = info_l1.ebx & 0xffff + + if os_map[i].pkg_id > max_pkg: + max_pkg = os_map[i].pkg_id + + bind_context(prev_context, None) + + # print(f"smt_id: {os_map[i].smt_id} core_id: {os_map[i].core_id} pkg_id: {os_map[i].pkg_id} os_id: {os_map[i].os_id}") + + num_pkg_cores = num_pkg_threads // num_core_threads + num_nodes = max_pkg + 1 + + # Construct a pkg map: pkg_map[pkg id][APIC_ID ... APIC_ID] + pkg_map = [[None] * num_pkg_threads for _ in range(num_nodes)] + + for i in range(os_cpu_count): + p = os_map[i].pkg_id + t = os_map[i].smt_id * num_pkg_cores + os_map[i].core_id + pkg_map[p][t] = os_map[i] + + for i in range(num_nodes): + for j in range(num_pkg_threads): + print(f"smt_id: {pkg_map[i][j].smt_id} core_id: {pkg_map[i][j].core_id} pkg_id: {pkg_map[i][j].pkg_id} os_id: {pkg_map[i][j].os_id}") + + return error diff --git a/rapl.py b/rapl.py new file mode 100644 index 0000000..2ec8522 --- /dev/null +++ b/rapl.py @@ -0,0 +1,52 @@ +import psutil +import time +import platform + +def get_energy(): + cpu_power = 0 + mem_power = 0 + if platform.system() == 'Linux': + with open('/sys/devices/virtual/powercap/intel-rapl/intel-rapl:0/energy_uj', 'r') as f: + cpu_energy_before = int(f.read().strip()) + with open('/sys/devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:1/energy_uj', 'r') as f: + mem_energy_before = int(f.read().strip()) + time.sleep(1) + with open('/sys/devices/virtual/powercap/intel-rapl/intel-rapl:0/energy_uj', 'r') as f: + cpu_energy_after = int(f.read().strip()) + with open('/sys/devices/virtual/powercap/intel-rapl/intel-rapl:0/intel-rapl:0:1/energy_uj', 'r') as f: + mem_energy_after = int(f.read().strip()) + cpu_energy_diff = cpu_energy_after - cpu_energy_before + mem_energy_diff = mem_energy_after - mem_energy_before + cpu_power = cpu_energy_diff / 1000000 # Convert uJ to mJ + mem_power = mem_energy_diff / 1000000 # Convert uJ to mJ + elif platform.system() == 'Windows': + cpu_percent_before = psutil.cpu_percent() + mem_percent_before = psutil.virtual_memory().percent + time.sleep(1) + cpu_percent_after = psutil.cpu_percent() + mem_percent_after = psutil.virtual_memory().percent + cpu_percent_diff = cpu_percent_after - cpu_percent_before + mem_percent_diff = mem_percent_after - mem_percent_before + cpu_power = cpu_percent_diff / 100 * psutil.cpu_count() * psutil.cpu_freq().current / 1000 + mem_power = mem_percent_diff / 100 * psutil.virtual_memory().total / 1024 / 1024 / 1024 * 3.3 + return (cpu_power, mem_power) + +print('Press Enter to start measuring energy consumption...') +input() +cpu_power_before, mem_power_before = get_energy() +print('Please write "math formula, word text, excel" using the virtual keyboard...') +while True: + try: + cpu_power, mem_power = get_energy() + cpu_power_diff = cpu_power - cpu_power_before + mem_power_diff = mem_power - mem_power_before + print(f'CPU energy consumption: {cpu_power_diff:.2f} mJ') + print(f'Memory energy consumption: {mem_power_diff:.2f} mJ') + time.sleep(1) + except KeyboardInterrupt: + break +cpu_power_after, mem_power_after = get_energy() +cpu_power_diff = cpu_power_after - cpu_power_before +mem_power_diff = mem_power_after - mem_power_before +print(f'Total CPU energy consumption: {cpu_power_diff:.2f} mJ') +print(f'Total memory energy consumption: {mem_power_diff:.2f} mJ') -- GitLab