# -*- coding: utf-8 -*- from abc import ABCMeta, 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 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.07 * 1.5 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':1.0, 'rome': 0.2, }[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.6, 'dell-poweredge-c4310': 0.6, 'dell-poweredge-r730': 0.4, '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 }[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-','') plt.scatter( x1, y1, facecolors=color, s=(markerSize * len(create_unique_marker(config_index))) , marker='$\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(b=True, which='major', color='b', linestyle='-', linewidth=0.5) plt.grid(b=True, which='minor', color='b', linestyle='-', linewidth=0.2) plt.legend(bbox_to_anchor=(1.1, 1.1), ncol=3) plt.draw() plt.show() def plot_configurators(configurators, ram_per_core, 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) if __name__ == '__main__': plot_2020_matinfo_configs