158 lines
5.2 KiB
Python
158 lines
5.2 KiB
Python
|
import re
|
||
|
|
||
|
from enum import Enum
|
||
|
|
||
|
class Stat(Enum):
|
||
|
CPU = 'cpu'
|
||
|
|
||
|
SOLVER = 'solver'
|
||
|
LIN_ALG = 'linear algebra'
|
||
|
INPUT_FILE = 'input file'
|
||
|
MAXWELL_SIZE = 'maxwell size'
|
||
|
MATRIX_COLS = 'matrix columns'
|
||
|
|
||
|
POWER_DELTA = 'Δ watt'
|
||
|
|
||
|
TASK_CLK = 'task clock (msec)'
|
||
|
PAGE_FAULTS = 'page faults'
|
||
|
CYCLES = 'cycles'
|
||
|
INSTS = 'instructions'
|
||
|
|
||
|
BR = 'branches'
|
||
|
BR_MISS = 'branch mispredictions'
|
||
|
ITLB = 'ITLB accesses'
|
||
|
ITLB_MISS = 'ITLB misses'
|
||
|
DTLB = 'DTLB accesses'
|
||
|
DTLB_MISS = 'DTLB misses'
|
||
|
L2D_TLB = 'L2D TLB accesses'
|
||
|
L2D_TLB_MISS = 'L2D TLB misses'
|
||
|
L1I_CACHE = 'L1I cache accesses'
|
||
|
L1I_CACHE_MISS = 'L1I cache misses'
|
||
|
L1D_CACHE = 'L1D cache accesses'
|
||
|
L1D_CACHE_MISS = 'L1D cache misses'
|
||
|
L2D_CACHE = 'L2D cache accesses'
|
||
|
L2D_CACHE_MISS = 'L2D cache misses'
|
||
|
LL_CACHE = 'LL cache accesses'
|
||
|
LL_CACHE_MISS = 'LL cache misses'
|
||
|
|
||
|
IPC = "instructions per cycle"
|
||
|
BRANCH_MISS_RATE = 'branch miss rate'
|
||
|
ITLB_MISS_RATE = 'ITLB miss rate'
|
||
|
DTLB_MISS_RATE = 'DTLB miss rate'
|
||
|
L2D_TLB_MISS_RATE = 'L2D TLB miss rate'
|
||
|
L1I_CACHE_MISS_RATE = 'L1I cache miss rate'
|
||
|
L1D_CACHE_MISS_RATE = 'L1D cache miss rate'
|
||
|
L2D_CACHE_MISS_RATE = 'L2D cache miss rate'
|
||
|
LL_CACHE_MISS_RATE = 'LL cache miss rate'
|
||
|
|
||
|
altra_names = {
|
||
|
Stat.TASK_CLK: 'task-clock:u',
|
||
|
Stat.PAGE_FAULTS: 'page-faults:u',
|
||
|
Stat.CYCLES: 'cycles:u',
|
||
|
Stat.INSTS: 'instructions:u',
|
||
|
|
||
|
Stat.BR: 'BR_RETIRED:u',
|
||
|
Stat.BR_MISS: 'BR_MIS_PRED_RETIRED:u',
|
||
|
Stat.ITLB: 'L1I_TLB:u',
|
||
|
Stat.ITLB_MISS: 'ITLB_WALK:u',
|
||
|
Stat.DTLB: 'L1D_TLB:u',
|
||
|
Stat.DTLB_MISS: 'DTLB_WALK:u',
|
||
|
Stat.L2D_TLB: 'L2D_TLB:u',
|
||
|
Stat.L2D_TLB_MISS: 'L2D_TLB_REFILL:u',
|
||
|
Stat.L1I_CACHE: 'L1I_CACHE:u',
|
||
|
Stat.L1I_CACHE_MISS: 'L1I_CACHE_REFILL:u',
|
||
|
Stat.L1D_CACHE: 'L1D_CACHE:u',
|
||
|
Stat.L1D_CACHE_MISS: 'L1D_CACHE_REFILL:u',
|
||
|
Stat.L2D_CACHE: 'L2D_CACHE:u',
|
||
|
Stat.L2D_CACHE_MISS: 'L2D_CACHE_REFILL:u',
|
||
|
Stat.LL_CACHE: 'LL_CACHE_RD:u',
|
||
|
Stat.LL_CACHE_MISS: 'LL_CACHE_MISS_RD:u',
|
||
|
}
|
||
|
|
||
|
xeon_names = {
|
||
|
Stat.TASK_CLK: 'task-clock:u',
|
||
|
Stat.PAGE_FAULTS: 'page-faults:u',
|
||
|
Stat.CYCLES: 'cycles:u',
|
||
|
Stat.INSTS: 'instructions:u',
|
||
|
|
||
|
Stat.BR: 'branches:u',
|
||
|
Stat.BR_MISS: 'branch-misses:u',
|
||
|
Stat.ITLB: 'iTLB-loads:u',
|
||
|
Stat.ITLB_MISS: 'iTLB-load-misses:u',
|
||
|
Stat.DTLB: 'dTLB-loads:u',
|
||
|
Stat.DTLB_MISS: 'dTLB-load-misses:u',
|
||
|
Stat.L1I_CACHE: 'L1-icache-loads:u',
|
||
|
Stat.L1I_CACHE_MISS: 'L1-icache-load-misses:u',
|
||
|
Stat.L1D_CACHE: 'L1-dcache-loads:u',
|
||
|
Stat.L1D_CACHE_MISS: 'L1-dcache-load-misses:u',
|
||
|
Stat.LL_CACHE: 'LLC-loads:u',
|
||
|
Stat.LL_CACHE_MISS: 'LLC-load-misses:u',
|
||
|
}
|
||
|
|
||
|
class CPU(Enum):
|
||
|
ALTRA = altra_names
|
||
|
XEON = xeon_names
|
||
|
|
||
|
def parse_output_old(filename: str, data: dict[str, str]) -> dict:
|
||
|
result: dict[str, int | float] = dict()
|
||
|
cpu: CPU = CPU[data['cpu'].upper()]
|
||
|
|
||
|
with open(filename, 'r') as file:
|
||
|
for line in file:
|
||
|
for stat in [x for x in Stat if x in cpu.value]:
|
||
|
regex = r'^\W*([\d+(,|\.)?]+)\W*.*' + cpu.value[stat]
|
||
|
value = re.search(regex, line)
|
||
|
|
||
|
if value is None:
|
||
|
continue
|
||
|
elif stat == Stat.TASK_CLK:
|
||
|
result[stat.value] = float(value.group(1).replace(',', ''))
|
||
|
else:
|
||
|
result[stat.value] = int(value.group(1).replace(',', ''))
|
||
|
|
||
|
return result | parse_power(filename, cpu)
|
||
|
|
||
|
def parse_output(output: str, cpu: CPU) -> dict:
|
||
|
result = dict()
|
||
|
|
||
|
for line in output.split('\n'):
|
||
|
for stat in [x for x in Stat if x in cpu.value]:
|
||
|
regex = r'^\W*([\d+(,|\.)?]+)\W*.*' + cpu.value[stat]
|
||
|
value = re.search(regex, line)
|
||
|
|
||
|
if value is None:
|
||
|
continue
|
||
|
elif stat == Stat.TASK_CLK:
|
||
|
result[stat.value] = float(value.group(1).replace(',', ''))
|
||
|
else:
|
||
|
result[stat.value] = int(value.group(1).replace(',', ''))
|
||
|
|
||
|
return result
|
||
|
|
||
|
def derive_stats(data: dict) -> dict:
|
||
|
result = dict()
|
||
|
|
||
|
result[Stat.IPC.value] = data[Stat.INSTS.value] / data[Stat.CYCLES.value]
|
||
|
result[Stat.BRANCH_MISS_RATE.value] = (
|
||
|
data[Stat.BR_MISS.value] / data[Stat.BR.value])
|
||
|
result[Stat.ITLB_MISS_RATE.value] = (
|
||
|
data[Stat.ITLB_MISS.value] / data[Stat.ITLB.value])
|
||
|
result[Stat.DTLB_MISS_RATE.value] = (
|
||
|
data[Stat.DTLB_MISS.value] / data[Stat.DTLB.value])
|
||
|
result[Stat.L2D_TLB_MISS_RATE.value] = (
|
||
|
data[Stat.L2D_TLB_MISS.value] / data[Stat.L2D_TLB.value]
|
||
|
if Stat.L2D_TLB_MISS.value in data and Stat.L2D_TLB.value in data
|
||
|
else None)
|
||
|
result[Stat.L1I_CACHE_MISS_RATE.value] = (
|
||
|
data[Stat.L1I_CACHE_MISS.value] / data[Stat.L1I_CACHE.value])
|
||
|
result[Stat.L1D_CACHE_MISS_RATE.value] = (
|
||
|
data[Stat.L1D_CACHE_MISS.value] / data[Stat.L1D_CACHE.value])
|
||
|
result[Stat.L2D_CACHE_MISS_RATE.value] = (
|
||
|
data[Stat.L2D_CACHE_MISS.value] / data[Stat.L2D_CACHE.value]
|
||
|
if Stat.L2D_CACHE_MISS.value in data and Stat.L2D_CACHE.value in data
|
||
|
else None)
|
||
|
result[Stat.LL_CACHE_MISS_RATE.value] = (
|
||
|
data[Stat.LL_CACHE_MISS.value] / data[Stat.LL_CACHE.value])
|
||
|
|
||
|
return result
|