concho/concho/procs_chooser.py

242 lines
8.2 KiB
Python

# -*- coding: utf-8 -*-
from typing import List
from abc import abstractmethod
import numpy
# import pylab
import matplotlib.pyplot as plt
import matplotlib.colors
import itertools
import re
import hashlib
# from string import ascii_lowercase
# from concho.config import Configurator
# from concho.config import Config
from concho.config import Cpu, MemSize, Configurator
# from concho import dell
markerTypes = [',', '+', '.', '^', 'v', '<', '>', 'o', '*', '1', '2', '3', '4', '8', 's', 'p', 'h', 'H', 'x', 'X', 'D', 'd', '|', '_']
# for c in ascii_lowercase:
# markerTypes.append('$%s$' % c)
# markerColors=('r', 'g', 'b')
markerColors = ('r')
def get_marker(proc_id):
hash_object = hashlib.md5(proc_id.encode('utf-8'))
hash = int(hash_object.hexdigest(), 16)
return markerTypes[hash % len(markerTypes)]
def plotCpuPassmark():
cpuTable = numpy.genfromtxt('cpu_table.tsv', dtype=("|U10", float, int, float, float), names=True, delimiter='\t')
plt.subplot(1, 1, 0)
plt.subplots_adjust(bottom=0.1)
markersCycler = itertools.cycle(itertools.product(markerTypes, markerColors))
labels = cpuTable['id']
x = cpuTable['clock'] * cpuTable['num_cores']
y = cpuTable['cpumark']
markerSize = 50
color = 'b'
for label, x1, y1 in zip(labels, x, y):
if y1 <= 0.0:
continue # no passmark available fo this data
generation = label[-1]
if generation == '2':
color = 'b'
else:
color = 'r'
marker = markersCycler.next()
plt.scatter(x1, y1, color=color, s=markerSize, marker=marker[0], label=label)
plt.xlabel(u'theoretical cpu speed [core.GHz]')
plt.ylabel(u'passmark [?]')
plt.title(u'comparison between cpu theoretical and effective speed')
plt.xlim(xmin=0.0)
plt.ylim(ymin=0.0)
plt.legend(bbox_to_anchor=(0.2, 1.0))
# plt.legend()
plt.draw()
plt.show()
def create_unique_marker(config_index):
marker_string = ''
alphabet_size = 26
alphabel_base = 0x41
while True:
digit_index = config_index % alphabet_size
marker_string = chr(alphabel_base + digit_index) + marker_string
if config_index < alphabet_size:
break
else:
config_index = config_index // alphabet_size
return marker_string
class ConfigAxisDef():
def __init__(self):
pass
@abstractmethod
def get_axis_label(self):
pass
@abstractmethod
def get_value_for_config(self, config):
pass
class ConfigPrice(ConfigAxisDef):
def get_axis_label(self):
return u'price [€]'
def get_value_for_config(self, config):
return config.get_price()
class ConfigFlops(ConfigAxisDef):
def get_axis_label(self):
return u'num total DP operations per second'
def get_value_for_config(self, config):
return config.get_flops()
class ConfigFlopsPerEuro(ConfigAxisDef):
def get_axis_label(self):
return u'num total DP operations/total cost [€/^-1]'
def get_value_for_config(self, config):
kWHPrice = 0.08 # from yjuet on 20/01/2023 : 300€/MWh
containerLifetime = 7.0 # in years
powerUsageEfficiency = 0.5
powerUsedInLifetime = (config.get_power_consumption() * containerLifetime * 365 * 24) / powerUsageEfficiency
itemTotalCost = config.get_price() + (powerUsedInLifetime / 1000.0 * kWHPrice)
item_total_num_ops = config.get_flops() * containerLifetime * 365 * 24 * 3600
return item_total_num_ops / itemTotalCost
def plot_configs(configs, xaxis_def, yaxis_def, plot_title):
"""
Args:
configs (list(Config)): the tist of configurations to plot
"""
def GHzToMHz(frequency):
return frequency * 1000.0
def getColorCodeFromItemLabel(label):
# generation = label[-1]
(num_servers, model, num_cpus, proc_id, ram_size) = re.split('_', label)
saturation = {
'sandy bridge': 0.0,
'ivy bridge': 0.2,
'haswell': 0.2,
'broadwell': 0.2,
'skylake': 0.4,
'coffeelake': 0.6,
'cascadelake': 0.8,
'icelake': 0.9,
'sapphire rapids': 1.0,
'rome': 0.8,
'milan': 1.0,
}[Cpu(proc_id).architecture]
# if model == 'r620':
# color = 'r'
# elif model == 'r630':
# color = 'g'
# elif model == 'r730':
# color = 'm'
# elif model == 'c6220':
# if generation == '2':
# color = 'b'
# else:
# color = 'y'
hue = {
'dell-poweredge-r620': 0.6,
'dell-poweredge-r630': 0.6,
'dell-poweredge-r640': 0.6,
'dell-poweredge-r6525': 0.5,
'dell-poweredge-c4310': 0.6,
'dell-poweredge-r730': 0.4,
'dell-poweredge-r7525': 0.3,
'dell-poweredge-r940': 0.8,
'dell-poweredge-c6220': 1.0,
'dell-poweredge-c6320': 1.0,
'dell-poweredge-c6420': 1.0,
'dell-precision-3630': 0.2,
'hpe-proliant-dl360-gen10': 0.3,
'hpe-proliant-dl360-gen10+': 0.55,
'hpe-proliant-dl385-gen10': 0.0,
'hpe-proliant-dl385-gen10+': 0.0,
'hpe-proliant-dl380-gen11': 0.1,
}[model]
value = 0.9
return matplotlib.colors.hsv_to_rgb((hue, saturation, value))
def get_marker_from_label(label):
(model, proc_id, ram_size) = re.split('_', label)
return get_marker(proc_id)
markerSize = 50
plt.subplot(1, 2, 1)
# markersCycler = itertools.cycle(itertools.product(markerTypes, markerColors))
config_index = 0
for config in configs:
cpu = config.cpu
config_label = str(config.num_servers) + '_' + config.chassis.uid + '_' + str(config.num_cpu_per_server) + '_' + cpu.uid + '_' + str(config.ram_size / config.num_servers) + 'gb'
x1 = xaxis_def.get_value_for_config(config)
y1 = yaxis_def.get_value_for_config(config)
print(config_label, x1, y1)
if y1 > 0.0001:
color = getColorCodeFromItemLabel(config_label)
# marker = markersCycler.next()
# marker = get_marker_from_label( label )
# print(x1, y1)
short_label = config_label.replace('dell-poweredge-', '').replace('intel-xeon-', '').replace('hpe-proliant-', '').replace('-gen', '-g')
plt.scatter(x1, y1, facecolors=color, s=(markerSize * len(create_unique_marker(config_index))), marker=r'$\mathrm{%s}$' % create_unique_marker(config_index), label=short_label)
if False: # y1 > 5.0e16:
plt.annotate(u'%s' % short_label,
xy=(x1, y1), xytext=(x1 * 4.0, (y1 - 5.2e16) * 7.1),
textcoords='data', ha='right', va='bottom',
bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5),
arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0'))
config_index += 1
plt.xlabel(xaxis_def.get_axis_label())
plt.ylabel(yaxis_def.get_axis_label())
plt.title(plot_title)
plt.xlim(xmin=0.0)
plt.ylim(ymin=0.0)
plt.minorticks_on()
plt.grid(visible=True, which='major', color='b', linestyle='-', linewidth=0.5)
plt.grid(visible=True, which='minor', color='b', linestyle='-', linewidth=0.2)
plt.legend(bbox_to_anchor=(1.1, 1.1), ncol=2)
plt.draw()
plt.show()
def plot_configurators(configurators: List[Configurator], ram_per_core: MemSize, xaxis_def, yaxis_def, plot_title, config_filter=lambda config: True):
configs = []
for configurator in configurators:
for cpu in configurator.get_cpu_options():
config = configurator.create_config()
config.num_cpu_per_server = int(min(config.configurator.chassis.item.num_cpu_slots_per_server, cpu.max_cpus))
config.set_cpu(cpu)
config.set_ram(ram_per_core=ram_per_core)
if config_filter(config):
configs.append(config)
plot_configs(configs, xaxis_def=xaxis_def, yaxis_def=yaxis_def, plot_title=plot_title)