From 93a8b772316a2833442673a1b98e20242c841fba Mon Sep 17 00:00:00 2001 From: Guillaume Raffy Date: Fri, 25 Sep 2020 16:35:13 +0200 Subject: [PATCH] refactored because the code was hard to maintain and was hacked in lots of ways (handling of 4 servers per host). - the prices are now retrived from matinfo's downloaded pages - the derived prices (such as the price without cpu) are now automatically computed, rather than hardcoded from (hand computation) - although it's a bit dirty, the architecture of the code is more generic: - each configuration is now stored in a Config object, which is able to compute its price. - dell specific code is now decoupled into a separate file. warnings: - the refactoring is designed to handle the old price tables but this work is not finished (the code using the old price tables is broken at the moment) - the computed price is currently overestimated, as the price of the base memory dimms should be substracted - disks are not currently handled --- concho/__init__.py | 0 concho/config.py | 371 ++++++++ concho/dell.py | 587 ++++++++++++ concho/procs_chooser.py | 242 +++++ cpu_table.dat | 309 ++++--- procs_chooser.py | 863 ------------------ ...64 - Cat2 Conf4 PowerEdge R640 - Dell.html | 604 ++++++++++++ readme.md | 3 +- setup.py | 7 + tests/test1.py | 10 + 10 files changed, 1977 insertions(+), 1019 deletions(-) create mode 100644 concho/__init__.py create mode 100644 concho/config.py create mode 100644 concho/dell.py create mode 100644 concho/procs_chooser.py delete mode 100644 procs_chooser.py create mode 100644 rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html create mode 100644 setup.py create mode 100644 tests/test1.py diff --git a/concho/__init__.py b/concho/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/concho/config.py b/concho/config.py new file mode 100644 index 0000000..700673c --- /dev/null +++ b/concho/config.py @@ -0,0 +1,371 @@ +import re +from abc import ABCMeta, abstractmethod +import numpy +from concho import dell + +class Item(): + + def __init__(self, uid): + self.uid = uid + + +class Chassis(Item): + + def __init__(self, uid): + super().__init__(uid) + self.max_num_servers = 1 + self.num_cpu_slots_per_server = 2 + if re.match('dell-poweredge-r9.*', uid): + self.num_cpu_slots_per_server = 4 + +class Dimm(Item): + + def __init__(self, num_gb, num_mhz, mem_type): + uid = "%s-%s-%s" % (mem_type, num_gb, num_mhz) + super().__init__(uid) + self.num_gb = num_gb + self.num_mhz = num_mhz + self.mem_type = mem_type + + +class Cpu(Item): + + def __init__(self, proc_id): + super().__init__(proc_id) + cpuTable = numpy.genfromtxt('cpu_table.dat', dtype=("|U32", float, int, float, float, float), names=True, delimiter='\t') + for cpu_id, clock, num_cores, tdp, cpumark in zip(cpuTable['id'], cpuTable['clock'], cpuTable['num_cores'], cpuTable['tdp'], cpuTable['cpumark_1_cpu']): + print(cpu_id) + if cpu_id == proc_id: + # print('found '+procId) + break + assert cpu_id == proc_id, 'Failed to find %s in cputable' % proc_id + self.clock = clock + self.num_cores = num_cores + self.tdp = tdp + self.cpumark = cpumark + + @property + def architecture(self): + proc_id = self.uid + if re.match('intel-core-i[357]-8[0-9][0-9][0-9][ktbuh]', proc_id): + return 'coffeelake' + elif re.match('intel-xeon-silver-[0-9]2[0-9][0-9]', proc_id): + return 'cascadelake' + elif re.match('intel-xeon-gold-[0-9]2[0-9][0-9]', proc_id): + return 'cascadelake' + elif re.match('intel-xeon-platinum-[0-9]2[0-9][0-9]', proc_id): + return 'cascadelake' + elif re.match('intel-xeon-gold-[0-9]1[0-9][0-9]', proc_id): + return 'skylake' + elif re.match('intel-xeon-platinum-[0-9]1[0-9][0-9]', proc_id): + return 'skylake' + elif re.match('intel-xeon-e5-26[0-9][0-9][lwa]*v4', proc_id): + return 'broadwell' + elif re.match('intel-xeon-e5-26[0-9][0-9][lwa]*v3', proc_id): + return 'haswell' + elif re.match('intel-xeon-e5-26[0-9][0-9][lwa]*v2', proc_id): + return 'ivy bridge' + elif re.match('intel-xeon-e5-26[0-9][0-9][lwa]*', proc_id): + return 'sandy bridge' + elif re.match('intel-xeon-x56[0-9][0-9]', proc_id): + return 'gulftown' + elif re.match('intel-xeon-x55[0-9][0-9]', proc_id): + return 'gainestown' + elif re.match('intel-xeon-e54[0-9][0-9]', proc_id): + return 'harpertown' + elif re.match('intel-xeon-51[0-9][0-9]', proc_id): + return 'woodcrest' + else: + assert False, 'unhandled processor id : %s' % proc_id + + @property + def num_dp_flop_per_cycle(self): + proc_arch = self.architecture + simd_id = get_simd_id(proc_arch) + num_simd_per_core = 1 + if proc_arch == 'skylake' or proc_arch == 'cascadelake': + # from https://en.wikipedia.org/wiki/List_of_Intel_Xeon_microprocessors : Xeon Platinum, Gold 61XX, and Gold 5122 have two AVX-512 FMA units per core; Xeon Gold 51XX (except 5122), Silver, and Bronze have a single AVX-512 FMA unit per core + if re.match('intel-xeon-gold-5122', self.uid): + num_simd_per_core = 2 + + # https://en.wikichip.org/wiki/intel/xeon_gold/5222 : 'Note that this is the only processor in the Xeon Gold 52xx series with two 512b FMA units.' + if re.match('intel-xeon-gold-5222', self.uid): + num_simd_per_core = 2 + + if re.match('intel-xeon-gold-61[0-9][0-9]', self.uid): + num_simd_per_core = 2 + if re.match('intel-xeon-gold-62[0-9][0-9]', self.uid): + num_simd_per_core = 2 + dp_flops_per_cycle = num_simd_per_core * simd_id_to_dp_flops_per_cycle(simd_id) + print(self.uid, dp_flops_per_cycle) + return dp_flops_per_cycle + + @property + def num_ram_channels(self): + return { + 'skylake': 6, + 'coffeelake': 6, + 'cascadelake': 6 + }[self.architecture] + +def get_proc_architecture(proc_id): + return Cpu(proc_id).architecture + +def get_proc_arch_transistor_size(proc_id): + return { + 'woodcrest':65, + 'harpertown':45, + 'gainestown':45, + 'gulftown':32, + 'sandy bridge':32, + 'ivy bridge':22, + 'haswell':22, + 'broadwell':14, + 'skylake':14, + 'coffeelake':14, + 'cascadelake':14 + }[get_proc_architecture(proc_id)] + +def simd_id_to_dp_flops_per_cycle(simd_id): + """ + :param str simd_id: eg 'avx2' + + """ + # from https://stackoverflow.com/questions/15655835/flops-per-cycle-for-sandy-bridge-and-haswell-sse2-avx-avx2 + # Intel Core 2 and Nehalem: + # + # 4 DP FLOPs/cycle: 2-wide SSE2 addition + 2-wide SSE2 multiplication + # 8 SP FLOPs/cycle: 4-wide SSE addition + 4-wide SSE multiplication + # + # Intel Sandy Bridge/Ivy Bridge: + # + # 8 DP FLOPs/cycle: 4-wide AVX addition + 4-wide AVX multiplication + # 16 SP FLOPs/cycle: 8-wide AVX addition + 8-wide AVX multiplication + # + # Intel Haswell/Broadwell/Skylake/Kaby Lake: + # + # 16 DP FLOPs/cycle: two 4-wide FMA (fused multiply-add) instructions + # 32 SP FLOPs/cycle: two 8-wide FMA (fused multiply-add) instructions + + return { + 'sse4.1':4, + 'sse4.2':4, + 'avx':8, + 'avx2':16, + 'avx-512':16, + }[simd_id] + +def get_simd_id(proc_arch): + """ + :param str proc_arch: eg 'broadwell' + :return str: eg 'sse4' + """ + return { + 'woodcrest':'sse4.1', + 'harpertown':'sse4.1', + 'gainestown':'sse4.2', + 'gulftown':'sse4.2', + 'sandy bridge':'avx', + 'ivy bridge':'avx', + 'haswell':'avx2', + 'broadwell':'avx2', + 'skylake':'avx-512', + 'cascadelake':'avx-512', + 'coffeelake':'avx2' + }[proc_arch] + + +class Config(): + + def __init__(self, configurator): + self.configurator = configurator + self.num_servers = 0 + self.num_cpu_per_server = 0 + self.cpu = None + self.dimms_per_channel = [] + + @property + def chassis(self): + return self.configurator.chassis.item + + def set_ram(self, ram_per_core=None, ram_per_server=None, ram_per_cpu=None): + + # ramUpgradePrice128Gb = { + # 'c6220':3520.0, + # 'r620':2010.0, + # 'r630':1778.0, + # 'r640':1780.0, + # 'r730':1778.0, + # 'r940':960.0, # 32 Gb 2933 MHz RDIMM : 320 € + # 'c6320':6222.6, + # 'c4310':1778.0, + # 'precision3630': 1536.0 } + cpu = self.cpu + if ram_per_cpu: + assert not ram_per_core + assert not ram_per_server + if ram_per_core: + assert not ram_per_server + assert not ram_per_cpu + ram_per_cpu = cpu.num_cores * ram_per_core + if ram_per_server: + assert not ram_per_core + assert not ram_per_cpu + ram_per_cpu = ram_per_server / self.num_cpu_per_server + + ram_per_channel = ram_per_cpu / cpu.num_ram_channels + dimm_capacity = None + if ram_per_channel > 64.0e9: + assert False, 'ram_per_channel is too big (%f bytes > 64 Gb)' % ram_per_channel + elif ram_per_channel > 32.0e9: + dimm_capacity = 64 + elif ram_per_channel > 16.0e9: + dimm_capacity = 32 + elif ram_per_channel > 8.0e9: + dimm_capacity = 16 + elif ram_per_channel > 4.0e9: + dimm_capacity = 8 + else: + try: + self.configurator.get_dimm_price(4) + dimm_capacity = 4 + except: + # 4Gb dimms are not available, use 8 Gb instead + dimm_capacity = 8 + # print('warning : forcing dimm capacity to 16G !!!!!!') + # dimm_capacity = 16 + dimm = self.configurator.get_dimm(dimm_capacity) + assert dimm + self.dimms_per_channel = [ dimm ] + + + def get_price(self): + price = self.configurator.chassis.price + price += self.num_servers * self.num_cpu_per_server * self.configurator.get_item_price(self.cpu.uid) + for dimm in self.dimms_per_channel: + dimm_price = self.configurator.get_item_price(dimm.uid) + price += self.num_servers * self.num_cpu_per_server * self.cpu.num_ram_channels * dimm_price + # print("ram_price : %f € for %d dimms of %d Gb" % (ram_price, self.num_servers * self.num_cpu_per_server * cpu.num_ram_channels, dimm_capacity)) + assert price > 0.0 + return price + + def get_power_consumption(self): + server_base_power_consumption = 100.0 # rough estimation in watts + power_consumption = (self.cpu.tdp * self.num_cpu_per_server + server_base_power_consumption) * self.num_servers + return power_consumption + + def get_flops(self): + flops = self.cpu.num_dp_flop_per_cycle * self.cpu.clock * 1.e9 * self.cpu.num_cores * self.num_cpu_per_server * self.num_servers + return flops + + + def set_cpu(self, cpu): + self.cpu = cpu + + +class Option(): + + def __init__(self, item, price): + self.item = item + self.price = price + +class Module(): + + def __init__(self, name): + self.name = name + self.options = {} + + def add_option(self, option): + self.options[option.item.uid] = option + + +class Configurator(): + + def __init__(self, name): + self.modules = {} + + @abstractmethod + def create_config(self): + assert False + + def add_module(self, module): + self.modules[module.name] = module + + def get_cpu_options(self): + return [Cpu(option.item.uid) for option in self.modules['processor'].options.values()] + + def get_ram_options(self): + return self.modules['ram'].values() + + def get_dimm(self, dimm_capacity): + for dimm_option in self.modules['ram'].options.values(): + dimm = dimm_option.item + # print(dimm.num_gb) + if dimm.num_gb == dimm_capacity: + return dimm + assert False, 'failed to find an option for a dimm of capacity %d gb' % dimm_capacity + + def get_item_price(self, item_uid): + for module in self.modules.values(): + if item_uid in module.options: + return module.options[item_uid].price + +class TableBasedConfigurator(Configurator): + + def __init__(self, host_type_id, num_cpu_per_server, num_servers=1): + self.host_type_id = host_type_id + self.num_cpu_per_server = num_cpu_per_server + self.num_servers = num_servers + self.dell_price_table = numpy.genfromtxt('dell_procoptions_table.dat', dtype=("|U15", "|U15", float), names=True, delimiter='\t') + self.base_config = Config(self) + self.base_config.num_servers = self.num_servers + self.base_config.num_cpu_per_server = self.num_cpu_per_server + + @abstractmethod + def get_empty_price(self): + pass + + @abstractmethod + def get_dimm_price(self, dimm_capacity): + pass + + @abstractmethod + def get_guarantee_price(self, guarantee_duration): + pass + + @abstractmethod + def get_disk_upgrade_price(self, disk_capacity): + pass + + def get_cpu_options(self): + supported_cpus = [] + for host_type_id, proc_id, proc_option_price in zip(self.dell_price_table['host_type_id'], self.dell_price_table['proc_id'], self.dell_price_table['proc_option_price']): + if host_type_id == self.host_type_id: + supported_cpus.append(Cpu(proc_id)) + return supported_cpus + + +# def create_host_type(host_type_id): +# if host_type_id == 'c6420': +# return dell.DellPowerEdgeC6420(host_type_id) +# if host_type_id == 'c6320': +# return dell.DellPowerEdgeC6320(host_type_id) +# if host_type_id == 'c4130': +# return dell.DellPowerEdgeC4130(host_type_id) +# if host_type_id == 'r620': +# return dell.DellPowerEdgeR620(host_type_id) +# if host_type_id == 'r630': +# return dell.DellPowerEdgeR630(host_type_id) +# if host_type_id == 'r640': +# return dell.DellPowerEdgeR640(host_type_id) +# if host_type_id == 'r940': +# return dell.DellPowerEdgeR940(host_type_id) +# if host_type_id == 'precision3630': +# return dell.DellPrecision3630(host_type_id) +# assert False + + + + + + # dom = parse(dell_configurator_html_file_path) diff --git a/concho/dell.py b/concho/dell.py new file mode 100644 index 0000000..259687b --- /dev/null +++ b/concho/dell.py @@ -0,0 +1,587 @@ +from concho.config import TableBasedConfigurator +from concho.config import Configurator +from concho.config import Module +from concho.config import Option +from concho.config import Config +from concho.config import Chassis +from concho.config import Cpu, Dimm + +from abc import ABCMeta, abstractmethod +from xml.dom.minidom import parse +from lxml.html import parse +import re +import copy + + +class DellPowerEdgeC6220(TableBasedConfigurator): + + def __init__(self): + super().__init__('c6220', num_cpu_per_server=2, num_servers=4) + + def get_empty_price(self): + return 4890.0 + + def get_guarantee_price(self, guarantee_duration): + assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id + return 880.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + return 320.0 + + +class DellPowerEdgeR620(TableBasedConfigurator): + + def __init__(self): + super().__init__('r620', num_cpu_per_server=2, num_servers=1) + + def get_empty_price(self): + return 860.0 + + def get_guarantee_price(self, guarantee_duration): + assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id + return 240.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + return -20.0 * self.num_servers + + +class DellPowerEdgeR630(TableBasedConfigurator): + + def __init__(self): + super().__init__('r630', num_cpu_per_server=2, num_servers=1) + + def get_empty_price(self): + # for r630 on 14/10/2016 + # (x: price without procs, p2603: price of e5-2603v4, p2609: price of e5-2609v4) + # we want to know x, given dell's web site, where we can get the price for multiple proc but not 0 + # x + p2603 = 948.0 + # x + 2 * p2603 = 948.0 + 216 + # => p2603 approx= 215.5 + # => x = 948. - 215. = 733.0 + # verification : + # x + p2609 = 1057.0 + # => p2609 = 1057-733=324.0 + # x + 2 * p2609 = 1381.0 + return 733.0 + + def get_guarantee_price(self, guarantee_duration): + assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id + return 240.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + return 0.0 * self.num_servers + +class DellPowerEdgeR730(TableBasedConfigurator): + + def __init__(self): + super().__init__('r730', num_cpu_per_server=2, num_servers=1) + + + def get_empty_price(self): + # for r730 on 06/10/2016 + # (x: price without procs, p1 : price of e5-2603v4, p2: price of e5-2609v4) + # we want to know x, given dell's web site, where we can get the price for multiple proc but not 0 + # x + p1 = 1014.0 + # x + 2 * p1 = 1014.0 + 216 + # => p1 approx= 215.5 + # => x = 1014. - 215. = 799.0 + # x + p2 = 1123.0 + # => p2 = 324.0 + # x + 2 * p2 = 1447.0 + return 799.0 + + def get_guarantee_price(self, guarantee_duration): + assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id + return 240.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + return 0.0 * self.num_servers + +class DellPowerEdgeC4130(TableBasedConfigurator): + + def __init__(self): + super().__init__('c4130', num_cpu_per_server=2, num_servers=1) + + def get_empty_price(self): + # for c4130 on 14/10/2016 + # x + 2 x E5-2640v4 + 128G + 2 * K80 + X520 + p5years = 12281€ + # x + 2 x E5-2640v4 + 128G + 4 * K80 + X520 + p5years = 19317€ + # price of a K80 + # >>> (19317.-12281)/2 + # 3518.0 + # assuming the options cost the same as for R630 (X520=210€, p5years=240€, 128G=1778€, E5-2640v4=951€), the cost of the base system is : + # >>> 12281-951-951-1778-210-240-3518-3518 + # 1115 + # but if we integrate the X520 card so that we have a 10Gb ethernet in the base, the cost of the base system becomes : + # >>> 1115+210 + # 1325 + return 1325.0 + + def get_guarantee_price(self, guarantee_duration): + assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id + return 240.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + return 0.0 * self.num_servers + + +class DellPowerEdgeC6320(TableBasedConfigurator): + + def __init__(self): + super().__init__('c6320', num_cpu_per_server=2, num_servers=4) + + def get_empty_price(self): + # for 4xc6320 on 14/10/2016 + # (x: price without procs, p2603: price of e5-2603v4, p2609: price of e5-2609v4) + # x + 4 x (2 x p2620 + p32G) = 5135 € HT + # x + 4 x (2 x p2640 + p128G + pX520 + p5years) = 15590 € HT + # x + 4 x (2 x p2650 + p128G + pX520 + p5years) = 17340 € HT + # x + 4 x (2 x p2660 + p128G + pX520 + p5years) = 19490 € HT + # by examining this and the price of processors on R630 + # - E5-2620v4 : 458€ + # - E5-2640v4 : 951€ + # - E5-2650v4 : 1209€ + # - E5-2660v4 : 1525€ + # - E5-2680v4 : 1867€ + # - E5-2690v4 : 2261€ + # I could work out that : + # - the price of procs on c6320 is the price of procs on r630 * 85% + # - the price of the base c6320 with 32 Go and no proc at all is 2020.6 + # - the price of the 32G to 128G upgrade is 6222.6 euros (cheaper price of 16G->128G upgrade on r630 : (1778*4 = 7112)) + # details : + # >>> (19490.-17340)/8 + # 268.75 + # >>> (17340.-15590)/8 + # 218.75 + # >>> 218.75/258. + # 0.8478682170542635 + # >>> 268.75/316 + # 0.8504746835443038 + # >>> 15590.0+((1209.0-951.0)*0.85)*8 + # 17344.4 + # >>> 15590.0+((1525.0-951.0)*0.85)*8 + # 19493.2 + # price of 128G ram upgrade assuming that 5years guarantee costs 880€ (same as c6220), + # >>> 15590.0+((458.0-951.0)*0.85)*8-210.0*4-880.0 - 5135.0 + # 6222.6 + # >>> 5135.0 - (458.0*0.85)*8 + # 2020.6 + return 2020.6 + + def get_guarantee_price(self, guarantee_duration): + assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id + return 880.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + return 0.0 * self.num_servers + + +class DellPowerEdgeR640(TableBasedConfigurator): + + def __init__(self): + super().__init__('r640', num_cpu_per_server=2, num_servers=1) + + def get_empty_price(self): + # on 29/09/2017 + # (x: price without procs, p3106: price of Bronze-3106, p6126: price of Gold6126) + # we want to know x, given dell's web site, where we can get the price for multiple proc but not 0 + # x + p3106 = 1067.0 + # x + 2 * p3106 = 1067.0 + 320.0 + # => p3106 = 320 + # => x = 1067.0 - 320.0 = 747.0 + # check if x computation is consistent with p6126 + # x + p6126 = 2767 + # x + 2 * p6126 = 4787.0 + # => p6126 = 2020.0 + # => x = 747.0 --> yes ! + return 747.0 + + def get_dimm_price(self, dimm_capacity): + return { + 8: 80.0, + 16: 160.0, + 32: 320.0, + 64: 640.0 + }[dimm_capacity] + + def get_guarantee_price(self, guarantee_duration): + if guarantee_duration > 7: + assert False, 'guarantee of more than 7 years is not available on %s' % self.host_type_id + elif guarantee_duration >= 5: + return 270.0 # from dell matinfo4 online quotation + else: + # 5-year guarantee included in base price + return 0.0 * self.num_servers + + @abstractmethod + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + # Retrait des disques de base (2x600Go 10K SAS 2.5'') : -260.0 € + # Ajout d'un disque dur 1,2 To SAS 10k Tpm 2,5" - hotplug : 165.0 € + base_disks_removal_price = -260.0 + disk_1200g_price = 165.0 + return (base_disks_removal_price + disk_1200g_price * 2) * self.num_servers + + +class DellPowerEdgeR940(TableBasedConfigurator): + + def __init__(self): + super().__init__('r940', num_cpu_per_server=4, num_servers=1) + + def get_empty_price(self): + # price of r940 (with 2x xeon gold 5215 and 32 Go DDR4 @ 2933GHz) on 09/06/2020 : 3784€ + # (x: price without procs, p5215: price of gold-5215, p6248: price of Gold6248) + # p6240 = 2684 + # p6248 = 3442 + # p8280l = 12075 + # x + 2 * p5215 = 3784 + # x + 4 * p6240 = 11886 => x = 1150 + # x + 4 * p6248 = 14918 => x = 1150 + # x + 4 * p8280l = 49450 => x = 1150 + # => p5215 = 1317 (agrees with proc price on r640) + return 1150.0 + + def get_dimm_price(self, dimm_capacity): + return { + 8: 80.0, + 16: 160.0, + 32: 320.0, + 64: 640.0 + }[dimm_capacity] + + def get_guarantee_price(self, guarantee_duration): + if guarantee_duration > 7: + assert False, 'guarantee of more than 7 years is not available on %s' % self.host_type_id + elif guarantee_duration >= 5: + return 630.0 # from dell matinfo4 online quotation + else: + # 5-year guarantee included in base price + return 0.0 + + @abstractmethod + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + # Retrait des disques de base (2x600Go 10K SAS 2.5'') : -260.0 € + # Ajout d'un disque dur 1,2 To SAS 10k Tpm 2,5" - hotplug : 165.0 € + base_disks_removal_price = -260.0 + disk_1200g_price = 165.0 + return (base_disks_removal_price + disk_1200g_price * 2) * self.num_servers + + +class DellPrecision3630(TableBasedConfigurator): + + def __init__(self): + super().__init__('prceision3630', num_cpu_per_server=1, num_servers=1) + + def get_empty_price(self): + return 449.0 + + def get_dimm_price(self, dimm_capacity): + return { + 8: 80.0, + 16: 160.0, + 32: 320.0 + }[dimm_capacity] + + def get_guarantee_price(self, guarantee_duration): + assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id + return 0.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + return 0.0 + +class DellPowerEdgeC6420(TableBasedConfigurator): + + def __init__(self, host_type_id): + super().__init__(host_type_id, num_cpu_per_server=2, num_servers=4) + + def get_empty_price(self): + # for 4xc6420 on 19/06/2020 (from excel quotation) + # + # + # (x: price without procs, p2630: price of xeon gold 6230) + # x + 4 x (2 x p4210r + p48g) = 5368 € HT + # x + 4 x (2 x p6230r + p192g) = 27213 € HT + # + # p48g = 3 * 160.0 # the price of a 16G ram is 160.0 € + # p4210r = p4210r=978./2 # from r640 prices + # + + # >>> p4210r=978./2 + # >>> p6230r_upgrade = 13408.0 + # >>> p6230r_for_r640 = 2165.0 + # >>> num_servers_per_c6000 = 4 + # >>> num_cpu_per_server = 2 + # >>> p6230r_for_c6420 = (p6230r_upgrade + p4210r * (num_servers_per_c6000 * num_cpu_per_server))/(num_servers_per_c6000 * num_cpu_per_server) + # >>> p6230r_for_c6420 + # 2165.0 + + # => p4210r seems to be the same on r640 and c6420 + # + # pc6000 = 5368 - (p4210r * num_cpu_per_server + p48g) * num_servers_per_c6000 + # >>> p16g = 160.0 + # >>> p48g = p16g * 3 + # >>> pc6000 = 5368 - (p4210r * num_cpu_per_server + p48g) * num_servers_per_c6000 + # >>> pc6000 + # -464.0 + # >>> pc6000 + num_servers_per_c6000 * (p6230r_for_c6420 * num_cpu_per_server + p192g) + # Traceback (most recent call last): + # File "", line 1, in + # NameError: name 'p192g' is not defined + # >>> p192g = (192/16)*p16g + # >>> p192g + # 1920.0 + # >>> pc6000 + num_servers_per_c6000 * (p6230r_for_c6420 * num_cpu_per_server + p192g) + # 24536.0 + # >>> pc6000 + num_servers_per_c6000 * (p6230r_for_c6420 * num_cpu_per_server + p192g) + 1159 + 68 + 350 + 1100 + # 27213.0 + num_servers_per_c6000 = 4 + num_cpu_per_server = 2 + ram_price_per_gigabyte = 160.0 / 16 # 16G ram price : 160.0 € + xeon_silver_4210r_price = 978.0 / 2 # from r640 prices + basic_config_price = 5368.0 + poweredge_c6000_price = basic_config_price - (xeon_silver_4210r_price * num_cpu_per_server + ram_price_per_gigabyte * 48) * num_servers_per_c6000 + return poweredge_c6000_price + + def get_dimm_price(self, dimm_capacity): + return { + 8: 80.0, + 16: 160.0, + 32: 320.0, + 64: 640.0 + }[dimm_capacity] + + def get_guarantee_price(self, guarantee_duration): + if guarantee_duration > 7: + assert False, 'guarantee of more than 7 years is not available on %s' % self.host_type_id + elif guarantee_duration >= 5: + return 1100.0 # from c6420-20200716-price + else: + # 5-year guarantee included in base price + return 0.0 + + def get_disk_upgrade_price(self, asked_disk_capacity): + assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id + # from c6420-20200716-price + # | Ajout d'un disque dur 1 To SATA 7200 Tpm 3,5'' pour les 4 serveurs | | 4-3-1-14g096 | C6420 | 361 € | | € - | + return 361.0 + + + + +class DellConfiguratorParser(): + + def __init__(self): + pass + + @classmethod + def _get_module(cls, root_element, section_label): + modules_element = root_element.xpath(".//div[@class='col-md-10']")[0] + # print(modules_element) + for module_root in modules_element.xpath(".//div[@class='col-md-12 module']"): + # print(module_root) + # blue modules such as "Processeurs (Passage)" + module_titles = module_root.xpath(".//div[@class='col-md-4 module-title color-017EB8']") + if len(module_titles) > 0: + # print(module_title.text) + # print(len(module_title.text)) + module_title = module_titles[0] + # print(module_title.text_content()) + if module_title.text == section_label: + return module_root + # grey modules such as 'Base' + module_titles = module_root.xpath(".//div[@class='col-md-4 module-title color-808080']") + if len(module_titles) > 0: + # print(module_title.text) + # print(len(module_title.text)) + module_title = module_titles[0] + # print(module_title.text_content()) + if module_title.text == section_label: + return module_root + + @classmethod + def price_str_as_float(cls, price_as_str): + match = re.match(r'^\s*(?P[-+]?)\s*(?P[0-9.]*)\s*€\s*$', price_as_str) + assert match + # print(match['sign'], match['numbers']) + price_as_float = float("%s%s" % (match['sign'], match['numbers'])) + return price_as_float + + + def _parse_proc_change_options(self, html_root): + proc_options = Module('processor-change') + #module_root_element = DellConfiguratorParser._get_module(html_root, 'Processeurs (Passage)') + module_root_element = DellConfiguratorParser._get_module(html_root, 'Processeurs (Passage)') + for option_root_element in module_root_element.xpath(".//div[@class='row']"): + label_elements = option_root_element.xpath(".//div[@class='option-not-selected ']") + if len(label_elements) > 0: + label = label_elements[0].text_content().replace('\n', '') + price = DellConfiguratorParser.price_str_as_float(option_root_element.xpath(".//div[@class='col-md-3 text-right option-price ']")[0].text_content()) + # print(label, price) + # Passage à processeur Intel Xeon Gold 6240L 2.6GHz, 24.75M Cache,10.40GT/s, 2UPI, Turbo, HT,18C/36T (150W) - DDR4-2933 + match = re.match(r'^Passage à processeur Intel Xeon (?PSilver|Gold|Platinium) (?P[0-9][0-9][0-9][0-9][RLYU]?).*', label) + assert match, 'unhandled label : %s' % label + # print(match['cpu_class'], match['cpu_number']) + cpu_class = match['cpu_class'].lower() + if cpu_class == 'platinium': + cpu_class = 'platinum' + cpu_id = "intel-xeon-%s-%s" % (cpu_class, match['cpu_number'].lower()) + option = Option(Cpu(cpu_id), price) + proc_options.add_option(option) + return proc_options + + def _parse_proc_options(self, html_root): + proc_options = Module('processor') + #module_root_element = DellConfiguratorParser._get_module(html_root, 'Processeurs (Passage)') + module_root_element = DellConfiguratorParser._get_module(html_root, 'Processeurs additionnels') + for option_root_element in module_root_element.xpath(".//div[@class='row']"): + label_elements = option_root_element.xpath(".//div[@class='option-not-selected ']") + if len(label_elements) > 0: + label = label_elements[0].text_content() + price = DellConfiguratorParser.price_str_as_float(option_root_element.xpath(".//div[@class='col-md-3 text-right option-price ']")[0].text_content()) + # print(label, price) + match = re.match(r'^Processeur additionnel Intel Xeon (?PSilver|Gold|Platinium) (?P[0-9][0-9][0-9][0-9][RLY]?).*', label) + assert match + # print(match['cpu_class'], match['cpu_number']) + cpu_class = match['cpu_class'].lower() + if cpu_class == 'platinium': + cpu_class = 'platinum' + cpu_id = "intel-xeon-%s-%s" % (cpu_class, match['cpu_number'].lower()) + option = Option(Cpu(cpu_id), price) + proc_options.add_option(option) + return proc_options + + def _parse_ram_options(self, html_root): + ram_options = Module('ram') + #module_root_element = DellConfiguratorParser._get_module(html_root, 'Processeurs (Passage)') + module_root_element = DellConfiguratorParser._get_module(html_root, 'Mémoire: Ajout de barettes additionnelles') + for option_root_element in module_root_element.xpath(".//div[@class='row']"): + label_elements = option_root_element.xpath(".//div[@class='option-not-selected ']") + if len(label_elements) > 0: + label = label_elements[0].text_content() + price = DellConfiguratorParser.price_str_as_float(option_root_element.xpath(".//div[@class='col-md-3 text-right option-price ']")[0].text_content()) + # print(label, price) + # Ajout d'une barette de 128Go 2667 Mhz LRDIMM + match = re.match(r'^Ajout d\'une barette de (?P[0-9]+)Go (?P[0-9][0-9][0-9][0-9]) Mhz (?PLRDIMM|RDIMM)$', label) + if match: + # print(match['num_gb'], match['num_mhz']) + dimm = Dimm(num_gb=int(match['num_gb']), num_mhz=int(match['num_mhz']), mem_type=match['mem_type'].lower()) + option = Option(dimm, price) + ram_options.add_option(option) + else: + # Optane DC Persistent Memory - 128Go 2666Mhz + match = re.match(r'^Optane DC Persistent Memory - (?P[0-9]+)Go (?P[0-9][0-9][0-9][0-9])Mhz$', label) + if match: + # print(match['num_gb'], match['num_mhz']) + dimm = Dimm(num_gb=int(match['num_gb']), num_mhz=int(match['num_mhz']), mem_type='pmm') # persistent memory module + option = Option(dimm, price) + ram_options.add_option(option) + else: + assert False, 'unhandled label : %s' % label + return ram_options + + def _parse_base_config(self, html_root, configurator): + base_config = Config(configurator) + base_config.num_servers = configurator.chassis.item.max_num_servers + base_config.num_cpu_per_server = 1 + module_root_element = DellConfiguratorParser._get_module(html_root, 'Processeurs (Passage)') + assert module_root_element is not None + for option_root_element in module_root_element.xpath(".//div[@class='row']"): + label_elements = option_root_element.xpath(".//div[@class='option-selected ']") + assert label_elements is not None + if len(label_elements) > 0: + label = label_elements[0].text_content().replace('\n', '') + price = DellConfiguratorParser.price_str_as_float(option_root_element.xpath(".//div[@class='col-md-3 text-right option-price option-price-selected']")[0].text_content()) + assert price == 0.0 + # print(label, price) + # Processeur Intel Xeon Silver 4208 2.1GHz,11M Cache,9.60GT/s, 2UPI,No Turbo, HT,8C/16T (85W) - DDR4-2400 + match = re.match(r'^Processeur Intel Xeon (?PSilver|Gold|Platinium) (?P[0-9][0-9][0-9][0-9][RLYU]?).*', label) + assert match, 'unhandled label : %s' % label + # print(match['cpu_class'], match['cpu_number']) + cpu_id = "intel-xeon-%s-%s" % (match['cpu_class'].lower(), match['cpu_number'].lower()) + base_config.set_cpu(Cpu(cpu_id)) + assert base_config.cpu is not None + return base_config + + + def parse(self, dell_configurator_html_file_path, configurator): + + html_root = parse(dell_configurator_html_file_path).getroot() + # print(dir(html_root)) + # for e in html_root: + # print(e.tag) + # body = html_root.find('body') + # print(body) + # for e in body: + # print(e.tag, e.attrib) + # div = body.find('div') + # for e in div: + # print(e.tag, e.attrib) + + # modules_element = body.xpath("//div[@class='col-md-10']") + + + module_root_element = DellConfiguratorParser._get_module(html_root, 'Base') + assert module_root_element is not None + for option_root_element in module_root_element.xpath(".//div[@class='row']"): + label_elements = option_root_element.xpath(".//div[@class='option-selected ']") + assert len(label_elements) > 0 + label = label_elements[0].text_content().replace('\n', '') + # PowerEdge R640 + match = re.match(r'^PowerEdge (?P[CR][0-9][0-9][0-9][0-9]?).*', label) + assert match, 'unhandled label : %s' % label + # print(match['cpu_class'], match['cpu_number']) + chassis_id = "dell-poweredge-%s" % (match['chassis_type'].lower(), ) + configurator.chassis = Option(Chassis(chassis_id), 0.0) + + configurator.base_config = self._parse_base_config(html_root, configurator) + + # configurator.add_module(self._parse_proc_change_options(html_root)) + configurator.add_module(self._parse_proc_options(html_root)) + configurator.add_module(self._parse_ram_options(html_root)) + + # compute the price of the chassis + base_price = None + price_preview_element = html_root.xpath(".//div[@class='price-preview']")[0] + assert price_preview_element is not None + for price_element in price_preview_element.xpath(".//div"): + price_label_element = price_element.xpath(".//span[@class='col-md-4']")[0] + #
+ #
Prix1175.00 €
+ #
Options0.00 €
+ #
Total1175.00 €
+ #
+ + assert price_label_element is not None + label = price_label_element.text_content().replace('\n', '') + if label == 'Prix': + price_value_element = price_element.xpath(".//span[@class='col-md-8']")[0] + assert price_value_element is not None + base_price = DellConfiguratorParser.price_str_as_float(price_value_element.text_content()) + assert base_price is not None + configurator.chassis.price = base_price - configurator.get_item_price(configurator.base_config.cpu.uid) + +class DellMatinfoConfigurator(Configurator): + + def __init__(self, dell_configurator_html_file_path): + super().__init__(self) + self.base_config = None + self.chassis = None + parser = DellConfiguratorParser() + parser.parse(dell_configurator_html_file_path, self) + + + def create_config(self): + return copy.copy(self.base_config) + diff --git a/concho/procs_chooser.py b/concho/procs_chooser.py new file mode 100644 index 0000000..490f7be --- /dev/null +++ b/concho/procs_chooser.py @@ -0,0 +1,242 @@ +# -*- coding: utf-8 -*- +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.dat', 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 plot_system_efficiency(): + + cpuTable = numpy.genfromtxt('cpu_table.dat', dtype=("|U15", float, int, float, float, float), names=True, delimiter='\t') + #cpuTable = numpy.genfromtxt('dell_ivybridge_table.dat', dtype=(('id', "|S10"), ('clock', float), ('num_cores', int), ('price', float, float)), names=None, delimiter='\t') + print(type(cpuTable)) + print(cpuTable.dtype) + print(cpuTable) + print(cpuTable['id']) + + #cpuTable = numpy.genfromtxt('dell_ivybridge_table.dat', dtype=(('id', "|S10"), ('clock', float), ('num_cores', int), ('price', float, float)), names=None, delimiter='\t') + + #for (x, y) in clusters: + def GHzToMHz( frequency ): + return frequency * 1000.0 + + kWHPrice = 0.07 * 1.5 + containerLifetime = 7.0 # in years + powerUsageEfficiency = 0.5 + + + def getColorCodeFromItemLabel(label): + generation=label[-1] + (model, proc_id) = 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 + }[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-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) = re.split('_', label) + return get_marker(proc_id) + + + item_price = numpy.array([]) + item_power_consumption = numpy.array([]) + item_speed = numpy.array([]) + item_label = numpy.array([]) + configurators = [ + dell.DellMatinfoConfigurator('rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html')] + # dell.DellPowerEdgeR940()] + for configurator in configurators: + config = configurator.create_config() + for cpu in configurator.get_cpu_options(): + if not cpu.architecture in ['coffeelake', 'skylake','cascadelake']: + continue + item_label = numpy.append( item_label, config.chassis.uid + '_' + cpu.uid ) + config.set_cpu(cpu) + config.set_ram(ram_per_core=4.0e9) + config.num_cpu_per_server = config.configurator.chassis.item.num_cpu_slots_per_server + # print('procOptionPrice', procOptionPrice) + # config_price = procOptionPrice + # config_price += config.get_empty_price() + # print('config.get_empty_price()', config.get_empty_price()) + # ram_update_price = config.get_ram_update_price(cpu=cpu, ram_per_core=4.0e9) + # # ram_update_price = config.get_ram_update_price(cpu=cpu, ram_per_server=192.0e9) + # # ram_update_price = config.get_ram_update_price(cpu=cpu, ram_per_cpu=96.0e9) + # print('ram_update_price', ram_update_price) + # config_price += ram_update_price + # config_price += config.get_guarantee_price(5) + # print('config.config.get_guarantee_price(5)', config.get_guarantee_price(5)) + # config_price += config.get_disk_upgrade_price(2.0e12) + # print('config.get_disk_upgrade_price(2.0e12)', config.get_disk_upgrade_price(2.0e12)) + item_price = numpy.append( item_price, config.get_price() ) + item_power_consumption = numpy.append( item_power_consumption, config.get_power_consumption()) + # # print(hostTypeId, procId, item_power_consumption[-1]) + item_speed = numpy.append( item_speed, config.get_flops()) + + #pylab.plot(x, y, '+') + #pylab.xlabel('speed/price ratio [core.MHz/euros]') + #pylab.ylabel('speed/power consumption ratio [core.MHz/W]') + #pylab.show() # or savefig() + + + #print("items = ") + #print(item_label) + + markerSize = 50 + + if False: + plt.subplot(1,2,1) + plt.subplots_adjust(bottom = 0.1) + markersCycler = itertools.cycle(itertools.product(markerTypes, markerColors)) + x = item_speed / item_price + y = item_speed / item_power_consumption + for label, x1, y1, power, speed, price, in zip(item_label, x, y, item_power_consumption, item_speed, item_price): + marker = markersCycler.next() + color = getColorCodeFromItemLabel(label) + plt.scatter( x1, y1, color = color, s = markerSize, marker = marker[0], label = label) + #print(x1, y1, color, markerSize, marker[0], label) + if False: + plt.scatter( x, y, marker = 'o') + for label, x1, y1, power, speed, price, in zip(item_label, x, y, item_power_consumption, item_speed, item_price): + #print(label) + plt.annotate( u'%s (%.1f core.GHz, %.0f W, %.0f €)' % (label,speed/1000.0, power, price), + xy = (x1, y1), xytext = (-50, 50), + textcoords = 'offset points', ha = 'right', va = 'bottom', + bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5), + arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0')) + plt.xlabel(u'speed/price ratio [core.MHz/€]') + plt.ylabel(u'speed/power consumption ratio [core.MHz/W]') + plt.xlim( xmin = 0.0 ) + plt.ylim( ymin = 0.0 ) + + plt.subplot(1,2,1) + #fig = plt.figure() + #ax = fig.gca() + #ax.set_xticks(numpy.arange(0,1,0.1)) + #ax.set_yticks(numpy.arange(0,1.,0.1)) + + powerUsedInLifetime = (item_power_consumption * containerLifetime * 365 * 24) / powerUsageEfficiency + itemTotalCost = item_price + (powerUsedInLifetime / 1000.0 * kWHPrice ) + markersCycler = itertools.cycle(itertools.product(markerTypes, markerColors)) + item_flops = item_speed + # print item_flops + item_total_num_ops = item_flops * containerLifetime * 365 * 24 * 3600 + print(item_price) + x = item_price + y = item_total_num_ops / itemTotalCost + for i in range(len(item_label)): + print(item_label[i], item_price[i], y[i]) + print('itemTotalCost', itemTotalCost[i]) + print('flops', item_flops[i]) + # print y + for label, x1, y1, power, speed, price, in zip(item_label, x, y, item_power_consumption, item_speed, item_price): + print(label, x1, y1) + if y1 > 0.0001: + color = getColorCodeFromItemLabel(label) + # marker = markersCycler.next() + marker = get_marker_from_label( label ) + #print(x1, y1) + short_label = label.replace('dell-poweredge-','').replace('intel-xeon-','') + plt.scatter( x1, y1, facecolors=color, s=markerSize, marker=marker[0], label=short_label) + if 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')) + + plt.xlabel(u'purchase price [€]') + plt.ylabel(u'num total DP operations/total cost [€/^-1]') + plt.title(u'total cost including electricity') + 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() + +#plotCpuPassmark(): +if __name__ == '__main__': + plot_system_efficiency() diff --git a/cpu_table.dat b/cpu_table.dat index 845f8a8..55f8210 100644 --- a/cpu_table.dat +++ b/cpu_table.dat @@ -1,158 +1,157 @@ #id clock num_cores tdp cpumark_1_cpu cpumark_2_cpu -core-i7-8700k 3.7 6 95 0 0 -5150 2.66 2 65 1746 3498 -E5462 2.8 4 80 4038 7350 -X5550 2.67 4 95 5416 9131 -X5560 2.8 4 95 5426 9215 -X5650 2.67 6 95 7601 11728 -X5660 2.8 6 95 7954 11893 -E5-2660 2.2 8 95 11535 17282 -E5-2670 2.6 8 115 0 18509 -E5-2680 2.7 8 130 0 18480 -E5-2690 2.9 8 135 0 20699 -E5-2620v2 2.1 6 95 8664 13474 -E5-2630v2 2.6 6 80 10615 16256 -E5-2640v2 2 8 95 10132 14792 -E5-2650v2 2.6 8 95 13276 19333 -E5-2660v2 2.2 10 95 13659 18670 -E5-2670v2 2.5 10 115 14892 22062 -E5-2680v2 2.8 10 115 16340 23263 -E5-2690v2 3 10 130 17304 24189 -E5-2695v2 2.4 12 130 17231 21980 -E5-2697v2 2.7 12 130 17516 23910 -E5-2603v3 1.6 6 85 4996 8358 -E5-2609v3 1.9 6 85 5878 9885 -E5-2620v3 2.4 6 85 9955 15400 -E5-2623v3 3 6 105 9007 13914 -E5-2630v3 2.4 8 85 12803 18699 -E5-2630Lv3 1.8 8 55 11201 0 -E5-2637v3 3.5 4 135 10278 16823 -E5-2640v3 2.6 8 90 14081 20824 -E5-2643v3 3.4 6 135 13671 20574 -E5-2650v3 2.3 10 105 15106 20602 -E5-2650Lv3 1.8 12 65 13132 0 -E5-2660v3 2.6 10 105 16161 23388 -E5-2667v3 3.2 8 135 16125 22935 -E5-2670v3 2.3 12 120 16549 22330 -E5-2680v3 2.5 12 120 18840 25352 -E5-2683v3 2 14 120 17917 22704 -E5-2687Wv3 3.1 10 160 17785 24769 -E5-2690v3 2.6 12 160 19567 26665 -E5-2695v3 2.3 14 120 20742 26021 -E5-2697v3 2.6 14 145 21667 29009 -E5-2698v3 2.3 16 135 21794 30217 -E5-2699v3 2.3 18 145 22520 24820 -E5-2603v4 1.7 6 85 5247 8809 -E5-2609v4 1.7 8 85 0 10835 -E5-2620v4 2.1 8 85 11219 17063 -E5-2623v4 2.6 4 85 0 10196 -E5-2630v4 2.2 10 85 14221 18281 -E5-2630Lv4 1.8 10 55 0 0 -E5-2637v4 3.5 4 135 9665 17398 -E5-2640v4 2.4 10 90 15244 21556 -E5-2643v4 3.4 6 135 14329 22063 -E5-2650v4 2.2 12 105 16212 22619 -E5-2650Lv4 1.7 14 65 0 0 -E5-2660v4 2.0 14 105 0 0 -E5-2667v4 3.2 8 135 0 0 -E5-2680v4 2.4 14 120 20489 0 -E5-2683v4 2.1 16 120 0 0 -E5-2687Wv4 3.0 12 160 20340 27161 -E5-2690v4 2.6 14 120 22843 28262 -E5-2695v4 2.1 18 135 19351 20768 -E5-2697v4 2.3 18 135 23070 0 -E5-2697Av4 2.6 16 145 0 24075 -E5-2698v4 2.2 20 135 24615 32248 -E5-2699v4 2.2 22 145 21277 38461 -Gold-5115 2.4 10 85 0 0 -Gold-5117 2.0 14 105 0 0 -Gold-5117F 2.0 14 113 0 0 -Gold-5117M 2.0 0 0 0 21250 -Gold-5118 2.3 12 105 0 0 -Gold-5119T 1.9 14 85 0 0 -Gold-5120 2.2 14 105 0 0 -Gold-5120T 2.2 14 105 0 0 -Gold-5122 3.6 4 105 0 0 -Gold-6126 2.6 12 125 0 0 -Gold-6126F 2.6 12 135 0 0 -Gold-6128 3.4 6 115 0 0 -Gold-6130 2.1 16 125 0 0 -Gold-6130F 2.1 16 125 0 0 -Gold-6130T 2.1 16 125 0 0 -Gold-6132 2.6 14 140 0 0 -Gold-6134 3.2 8 130 0 0 -Gold-6134M 3.2 8 130 0 0 -Gold-6136 3.0 12 150 0 0 -Gold-6138 2.0 20 125 0 0 -Gold-6138F 2.0 20 135 0 0 -Gold-6138T 2.0 20 125 0 0 -Gold-6140 2.3 18 140 0 0 -Gold-6140M 2.3 18 140 0 0 -Gold-6142 2.6 16 150 0 0 -Gold-6142F 2.6 16 160 0 0 -Gold-6142M 2.6 16 150 0 0 -Gold-6144 3.5 8 150 0 0 -Gold-6145 2.0 20 145 0 0 -Gold-6146 3.2 12 165 0 0 -Gold-6148 2.4 20 150 0 0 -Gold-6150 2.7 18 165 0 26349 -Gold-6152 2.1 22 140 0 0 -Gold-6154 3.0 18 200 0 0 -Gold-6161 2.2 22 165 0 0 +intel-core-i7-8700k 3.7 6 95 0 0 +intel-xeon-5150 2.66 2 65 1746 3498 +intel-xeon-e5462 2.8 4 80 4038 7350 +intel-xeon-x5550 2.67 4 95 5416 9131 +intel-xeon-x5560 2.8 4 95 5426 9215 +intel-xeon-x5650 2.67 6 95 7601 11728 +intel-xeon-x5660 2.8 6 95 7954 11893 +intel-xeon-e5-2660 2.2 8 95 11535 17282 +intel-xeon-e5-2670 2.6 8 115 0 18509 +intel-xeon-e5-2680 2.7 8 130 0 18480 +intel-xeon-e5-2690 2.9 8 135 0 20699 +intel-xeon-e5-2620v2 2.1 6 95 8664 13474 +intel-xeon-e5-2630v2 2.6 6 80 10615 16256 +intel-xeon-e5-2640v2 2 8 95 10132 14792 +intel-xeon-e5-2650v2 2.6 8 95 13276 19333 +intel-xeon-e5-2660v2 2.2 10 95 13659 18670 +intel-xeon-e5-2670v2 2.5 10 115 14892 22062 +intel-xeon-e5-2680v2 2.8 10 115 16340 23263 +intel-xeon-e5-2690v2 3 10 130 17304 24189 +intel-xeon-e5-2695v2 2.4 12 130 17231 21980 +intel-xeon-e5-2697v2 2.7 12 130 17516 23910 +intel-xeon-e5-2603v3 1.6 6 85 4996 8358 +intel-xeon-e5-2609v3 1.9 6 85 5878 9885 +intel-xeon-e5-2620v3 2.4 6 85 9955 15400 +intel-xeon-e5-2623v3 3 6 105 9007 13914 +intel-xeon-e5-2630v3 2.4 8 85 12803 18699 +intel-xeon-e5-2630lv3 1.8 8 55 11201 0 +intel-xeon-e5-2637v3 3.5 4 135 10278 16823 +intel-xeon-e5-2640v3 2.6 8 90 14081 20824 +intel-xeon-e5-2643v3 3.4 6 135 13671 20574 +intel-xeon-e5-2650v3 2.3 10 105 15106 20602 +intel-xeon-e5-2650lv3 1.8 12 65 13132 0 +intel-xeon-e5-2660v3 2.6 10 105 16161 23388 +intel-xeon-e5-2667v3 3.2 8 135 16125 22935 +intel-xeon-e5-2670v3 2.3 12 120 16549 22330 +intel-xeon-e5-2680v3 2.5 12 120 18840 25352 +intel-xeon-e5-2683v3 2 14 120 17917 22704 +intel-xeon-e5-2687wv3 3.1 10 160 17785 24769 +intel-xeon-e5-2690v3 2.6 12 160 19567 26665 +intel-xeon-e5-2695v3 2.3 14 120 20742 26021 +intel-xeon-e5-2697v3 2.6 14 145 21667 29009 +intel-xeon-e5-2698v3 2.3 16 135 21794 30217 +intel-xeon-e5-2699v3 2.3 18 145 22520 24820 +intel-xeon-e5-2603v4 1.7 6 85 5247 8809 +intel-xeon-e5-2609v4 1.7 8 85 0 10835 +intel-xeon-e5-2620v4 2.1 8 85 11219 17063 +intel-xeon-e5-2623v4 2.6 4 85 0 10196 +intel-xeon-e5-2630v4 2.2 10 85 14221 18281 +intel-xeon-e5-2630lv4 1.8 10 55 0 0 +intel-xeon-e5-2637v4 3.5 4 135 9665 17398 +intel-xeon-e5-2640v4 2.4 10 90 15244 21556 +intel-xeon-e5-2643v4 3.4 6 135 14329 22063 +intel-xeon-e5-2650v4 2.2 12 105 16212 22619 +intel-xeon-e5-2650lv4 1.7 14 65 0 0 +intel-xeon-e5-2660v4 2.0 14 105 0 0 +intel-xeon-e5-2667v4 3.2 8 135 0 0 +intel-xeon-e5-2680v4 2.4 14 120 20489 0 +intel-xeon-e5-2683v4 2.1 16 120 0 0 +intel-xeon-e5-2687wv4 3.0 12 160 20340 27161 +intel-xeon-e5-2690v4 2.6 14 120 22843 28262 +intel-xeon-e5-2695v4 2.1 18 135 19351 20768 +intel-xeon-e5-2697v4 2.3 18 135 23070 0 +intel-xeon-e5-2697av4 2.6 16 145 0 24075 +intel-xeon-e5-2698v4 2.2 20 135 24615 32248 +intel-xeon-e5-2699v4 2.2 22 145 21277 38461 +intel-xeon-gold-5115 2.4 10 85 0 0 +intel-xeon-gold-5117 2.0 14 105 0 0 +intel-xeon-gold-5117f 2.0 14 113 0 0 +intel-xeon-gold-5117m 2.0 0 0 0 21250 +intel-xeon-gold-5118 2.3 12 105 0 0 +intel-xeon-gold-5119t 1.9 14 85 0 0 +intel-xeon-gold-5120 2.2 14 105 0 0 +intel-xeon-gold-5120t 2.2 14 105 0 0 +intel-xeon-gold-5122 3.6 4 105 0 0 +intel-xeon-gold-6126 2.6 12 125 0 0 +intel-xeon-gold-6126f 2.6 12 135 0 0 +intel-xeon-gold-6128 3.4 6 115 0 0 +intel-xeon-gold-6130 2.1 16 125 0 0 +intel-xeon-gold-6130f 2.1 16 125 0 0 +intel-xeon-gold-6130t 2.1 16 125 0 0 +intel-xeon-gold-6132 2.6 14 140 0 0 +intel-xeon-gold-6134 3.2 8 130 0 0 +intel-xeon-gold-6134m 3.2 8 130 0 0 +intel-xeon-gold-6136 3.0 12 150 0 0 +intel-xeon-gold-6138 2.0 20 125 0 0 +intel-xeon-gold-6138f 2.0 20 135 0 0 +intel-xeon-gold-6138t 2.0 20 125 0 0 +intel-xeon-gold-6140 2.3 18 140 0 0 +intel-xeon-gold-6140m 2.3 18 140 0 0 +intel-xeon-gold-6142 2.6 16 150 0 0 +intel-xeon-gold-6142f 2.6 16 160 0 0 +intel-xeon-gold-6142m 2.6 16 150 0 0 +intel-xeon-gold-6144 3.5 8 150 0 0 +intel-xeon-gold-6145 2.0 20 145 0 0 +intel-xeon-gold-6146 3.2 12 165 0 0 +intel-xeon-gold-6148 2.4 20 150 0 0 +intel-xeon-gold-6150 2.7 18 165 0 26349 +intel-xeon-gold-6152 2.1 22 140 0 0 +intel-xeon-gold-6154 3.0 18 200 0 0 +intel-xeon-gold-6161 2.2 22 165 0 0 -Silver-4208 2.1 8 85 0 0 -Silver-4210R 2.4 10 100 0 0 -Silver-4214R 2.4 12 100 0 0 -Silver-4214Y 2.2 12 85 0 0 -Silver-4215R 3.2 8 130 0 0 -Silver-4216 2.1 16 100 0 0 -Gold-5215 2.5 10 85 0 0 -Gold-5215L 2.5 10 85 0 0 -Gold-5217 3.0 8 115 0 0 -Gold-5218 2.3 16 125 0 0 -Gold-5218R 2.1 20 125 0 0 -Gold-5220 2.2 18 125 0 0 -Gold-5220R 2.2 24 150 0 0 -Gold-5222 3.8 4 105 0 0 -Gold-6210U 2.5 20 150 0 0 -Gold-6212U 2.4 24 165 0 0 -Gold-6226 2.7 12 125 0 0 -Gold-6226R 2.9 16 150 0 0 -Gold-6230 2.1 20 125 0 0 -Gold-6230R 2.1 26 150 0 0 -Gold-6234 3.3 8 130 0 0 -Gold-6238 2.1 22 140 0 0 -Gold-6238L 2.1 22 140 0 0 -Gold-6238R 2.2 28 165 0 0 -Gold-6240 2.6 18 150 0 0 -Gold-6240L 2.6 18 150 0 0 -Gold-6240R 2.4 24 165 0 0 -Gold-6240Y 2.6 18 150 0 0 -Gold-6242 2.8 16 150 0 0 -Gold-6242R 3.1 20 205 0 0 -Gold-6244 3.6 8 150 0 0 -Gold-6246 3.3 12 165 0 0 -Gold-6246R 3.4 16 205 0 0 -Gold-6248 2.5 20 150 0 0 -Gold-6248R 3.0 24 205 0 0 -Gold-6252 2.1 24 150 0 0 -Gold-6254 3.1 18 200 0 0 -Gold-6258R 2.7 28 205 0 0 -Platinum-8256 3.8 4 105 0 0 -Platinum-8260 2.4 24 165 0 0 -Platinum-8260L 2.4 24 165 0 0 -Platinum-8260Y 2.4 24 165 0 0 -Platinum-8253 2.2 16 125 0 0 -Platinum-8268 2.9 24 205 0 0 -Platinum-8270 2.7 26 205 0 0 -Platinum-8276 2.2 28 165 0 0 -Platinum-8280 2.7 28 205 0 0 -Platinum-8280L 2.7 28 205 0 0 - -Platinum-8153 2.0 16 125 0 0 -Platinum-8160 2.1 24 150 0 0 -Platinum-8164 2.0 26 165 0 0 -Platinum-8168 2.7 24 205 0 0 -Platinum-8170 2.1 26 165 0 0 -Platinum-8176 2.1 28 165 0 0 +intel-xeon-silver-4208 2.1 8 85 0 0 +intel-xeon-silver-4210r 2.4 10 100 0 0 +intel-xeon-silver-4214r 2.4 12 100 0 0 +intel-xeon-silver-4214y 2.2 12 85 0 0 +intel-xeon-silver-4215r 3.2 8 130 0 0 +intel-xeon-silver-4216 2.1 16 100 0 0 +intel-xeon-gold-5215 2.5 10 85 0 0 +intel-xeon-gold-5215l 2.5 10 85 0 0 +intel-xeon-gold-5217 3.0 8 115 0 0 +intel-xeon-gold-5218 2.3 16 125 0 0 +intel-xeon-gold-5218r 2.1 20 125 0 0 +intel-xeon-gold-5220 2.2 18 125 0 0 +intel-xeon-gold-5220r 2.2 24 150 0 0 +intel-xeon-gold-5222 3.8 4 105 0 0 +intel-xeon-gold-6210u 2.5 20 150 0 0 +intel-xeon-gold-6212u 2.4 24 165 0 0 +intel-xeon-gold-6226 2.7 12 125 0 0 +intel-xeon-gold-6226r 2.9 16 150 0 0 +intel-xeon-gold-6230 2.1 20 125 0 0 +intel-xeon-gold-6230r 2.1 26 150 0 0 +intel-xeon-gold-6234 3.3 8 130 0 0 +intel-xeon-gold-6238 2.1 22 140 0 0 +intel-xeon-gold-6238l 2.1 22 140 0 0 +intel-xeon-gold-6238r 2.2 28 165 0 0 +intel-xeon-gold-6240 2.6 18 150 0 0 +intel-xeon-gold-6240l 2.6 18 150 0 0 +intel-xeon-gold-6240r 2.4 24 165 0 0 +intel-xeon-gold-6240y 2.6 18 150 0 0 +intel-xeon-gold-6242 2.8 16 150 0 0 +intel-xeon-gold-6242r 3.1 20 205 0 0 +intel-xeon-gold-6244 3.6 8 150 0 0 +intel-xeon-gold-6246 3.3 12 165 0 0 +intel-xeon-gold-6246r 3.4 16 205 0 0 +intel-xeon-gold-6248 2.5 20 150 0 0 +intel-xeon-gold-6248r 3.0 24 205 0 0 +intel-xeon-gold-6252 2.1 24 150 0 0 +intel-xeon-gold-6254 3.1 18 200 0 0 +intel-xeon-gold-6258r 2.7 28 205 0 0 +intel-xeon-platinum-8256 3.8 4 105 0 0 +intel-xeon-platinum-8260 2.4 24 165 0 0 +intel-xeon-platinum-8260l 2.4 24 165 0 0 +intel-xeon-platinum-8260y 2.4 24 165 0 0 +intel-xeon-platinum-8253 2.2 16 125 0 0 +intel-xeon-platinum-8268 2.9 24 205 0 0 +intel-xeon-platinum-8270 2.7 26 205 0 0 +intel-xeon-platinum-8276 2.2 28 165 0 0 +intel-xeon-platinum-8280 2.7 28 205 0 0 +intel-xeon-platinum-8280l 2.7 28 205 0 0 +intel-xeon-platinum-8153 2.0 16 125 0 0 +intel-xeon-platinum-8160 2.1 24 150 0 0 +intel-xeon-platinum-8164 2.0 26 165 0 0 +intel-xeon-platinum-8168 2.7 24 205 0 0 +intel-xeon-platinum-8170 2.1 26 165 0 0 +intel-xeon-platinum-8176 2.1 28 165 0 0 diff --git a/procs_chooser.py b/procs_chooser.py deleted file mode 100644 index 0bbe3a9..0000000 --- a/procs_chooser.py +++ /dev/null @@ -1,863 +0,0 @@ -# -*- coding: utf-8 -*- -import numpy -import pylab -import matplotlib.pyplot as plt -import matplotlib.colors -import itertools -import re -import hashlib -from string import ascii_lowercase -from abc import ABCMeta, abstractmethod - -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.dat', 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() - - -class Cpu(): - - def __init__(self, proc_id): - cpuTable = numpy.genfromtxt('cpu_table.dat', dtype=("|U15", float, int, float, float, float), names=True, delimiter='\t') - for id, clock, num_cores, tdp, cpumark in zip(cpuTable['id'], cpuTable['clock'], cpuTable['num_cores'], cpuTable['tdp'], cpuTable['cpumark_1_cpu']): - if id == proc_id: - # print('found '+procId) - break - assert id == proc_id, 'Failed to find %s in cputable' % proc_id - self.proc_id = proc_id - self.clock = clock - self.num_cores = num_cores - self.tdp = tdp - self.cpumark = cpumark - - @property - def architecture(self): - proc_id = self.proc_id - if re.match('core-i[357]-8[0-9][0-9][0-9][ktbuh]', proc_id): - return 'coffeelake' - elif re.match('Silver-[0-9]2[0-9][0-9]', proc_id): - return 'cascadelake' - elif re.match('Gold-[0-9]2[0-9][0-9]', proc_id): - return 'cascadelake' - elif re.match('Platinum-[0-9]2[0-9][0-9]', proc_id): - return 'cascadelake' - elif re.match('Gold-[0-9]1[0-9][0-9]', proc_id): - return 'skylake' - elif re.match('Platinum-[0-9]1[0-9][0-9]', proc_id): - return 'skylake' - elif re.match('E5-26[0-9][0-9][LWA]*v4', proc_id): - return 'broadwell' - elif re.match('E5-26[0-9][0-9][LWA]*v3', proc_id): - return 'haswell' - elif re.match('E5-26[0-9][0-9][LWA]*v2', proc_id): - return 'ivy bridge' - elif re.match('E5-26[0-9][0-9][LWA]*', proc_id): - return 'sandy bridge' - elif re.match('X56[0-9][0-9]', proc_id): - return 'gulftown' - elif re.match('X55[0-9][0-9]', proc_id): - return 'gainestown' - elif re.match('E54[0-9][0-9]', proc_id): - return 'harpertown' - elif re.match('51[0-9][0-9]', proc_id): - return 'woodcrest' - else: - assert False - - @property - def num_dp_flop_per_cycle(self): - proc_arch = self.architecture - simd_id = get_simd_id(proc_arch) - num_simd_per_core = 1 - if proc_arch == 'skylake' or proc_arch == 'cascadelake': - # from https://en.wikipedia.org/wiki/List_of_Intel_Xeon_microprocessors : Xeon Platinum, Gold 61XX, and Gold 5122 have two AVX-512 FMA units per core; Xeon Gold 51XX (except 5122), Silver, and Bronze have a single AVX-512 FMA unit per core - if re.match('Gold-5122', self.proc_id): - num_simd_per_core = 2 - - # https://en.wikichip.org/wiki/intel/xeon_gold/5222 : 'Note that this is the only processor in the Xeon Gold 52xx series with two 512b FMA units.' - if re.match('Gold-5222', self.proc_id): - num_simd_per_core = 2 - - if re.match('Gold-61[0-9][0-9]', self.proc_id): - num_simd_per_core = 2 - if re.match('Gold-62[0-9][0-9]', self.proc_id): - num_simd_per_core = 2 - dp_flops_per_cycle = num_simd_per_core * simd_id_to_dp_flops_per_cycle(simd_id) - print(self.proc_id, dp_flops_per_cycle) - return dp_flops_per_cycle - - @property - def num_ram_channels(self): - return { - 'skylake': 6, - 'coffeelake': 6, - 'cascadelake': 6 - }[self.architecture] - -def get_proc_architecture(proc_id): - return Cpu(proc_id).architecture - -def get_proc_arch_transistor_size(proc_id): - return { - 'woodcrest':65, - 'harpertown':45, - 'gainestown':45, - 'gulftown':32, - 'sandy bridge':32, - 'ivy bridge':22, - 'haswell':22, - 'broadwell':14, - 'skylake':14, - 'coffeelake':14, - 'cascadelake':14 - }[get_proc_architecture(proc_id)] - -def simd_id_to_dp_flops_per_cycle(simd_id): - """ - :param str simd_id: eg 'avx2' - - """ - # from https://stackoverflow.com/questions/15655835/flops-per-cycle-for-sandy-bridge-and-haswell-sse2-avx-avx2 - # Intel Core 2 and Nehalem: - # - # 4 DP FLOPs/cycle: 2-wide SSE2 addition + 2-wide SSE2 multiplication - # 8 SP FLOPs/cycle: 4-wide SSE addition + 4-wide SSE multiplication - # - # Intel Sandy Bridge/Ivy Bridge: - # - # 8 DP FLOPs/cycle: 4-wide AVX addition + 4-wide AVX multiplication - # 16 SP FLOPs/cycle: 8-wide AVX addition + 8-wide AVX multiplication - # - # Intel Haswell/Broadwell/Skylake/Kaby Lake: - # - # 16 DP FLOPs/cycle: two 4-wide FMA (fused multiply-add) instructions - # 32 SP FLOPs/cycle: two 8-wide FMA (fused multiply-add) instructions - - return { - 'sse4.1':4, - 'sse4.2':4, - 'avx':8, - 'avx2':16, - 'avx-512':16, - }[simd_id] - -def get_simd_id(proc_arch): - """ - :param str proc_arch: eg 'broadwell' - :return str: eg 'sse4' - """ - return { - 'woodcrest':'sse4.1', - 'harpertown':'sse4.1', - 'gainestown':'sse4.2', - 'gulftown':'sse4.2', - 'sandy bridge':'avx', - 'ivy bridge':'avx', - 'haswell':'avx2', - 'broadwell':'avx2', - 'skylake':'avx-512', - 'cascadelake':'avx-512', - 'coffeelake':'avx2' - }[proc_arch] - - -class HostType(): - - def __init__(self, host_type_id, num_cpu_per_server, num_servers=1): - self.host_type_id = host_type_id - self.num_cpu_per_server = num_cpu_per_server - self.num_servers = num_servers - - @abstractmethod - def get_empty_price(self): - pass - - @abstractmethod - def get_dimm_price(self, dimm_capacity): - pass - - @abstractmethod - def get_guarantee_price(self, guarantee_duration): - pass - - @abstractmethod - def get_disk_upgrade_price(self, disk_capacity): - pass - - -class DellPowerEdgeC6220(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=4) - - def get_empty_price(self): - return 4890.0 - - def get_guarantee_price(self, guarantee_duration): - assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id - return 880.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - return 320.0 - - -class DellPowerEdgeR620(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=1) - - def get_empty_price(self): - return 860.0 - - def get_guarantee_price(self, guarantee_duration): - assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id - return 240.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - return -20.0 * self.num_servers - - -class DellPowerEdgeR630(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=1) - - def get_empty_price(self): - # for r630 on 14/10/2016 - # (x: price without procs, p2603: price of e5-2603v4, p2609: price of e5-2609v4) - # we want to know x, given dell's web site, where we can get the price for multiple proc but not 0 - # x + p2603 = 948.0 - # x + 2 * p2603 = 948.0 + 216 - # => p2603 approx= 215.5 - # => x = 948. - 215. = 733.0 - # verification : - # x + p2609 = 1057.0 - # => p2609 = 1057-733=324.0 - # x + 2 * p2609 = 1381.0 - return 733.0 - - def get_guarantee_price(self, guarantee_duration): - assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id - return 240.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - return 0.0 * self.num_servers - -class DellPowerEdgeR730(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=1) - - - def get_empty_price(self): - # for r730 on 06/10/2016 - # (x: price without procs, p1 : price of e5-2603v4, p2: price of e5-2609v4) - # we want to know x, given dell's web site, where we can get the price for multiple proc but not 0 - # x + p1 = 1014.0 - # x + 2 * p1 = 1014.0 + 216 - # => p1 approx= 215.5 - # => x = 1014. - 215. = 799.0 - # x + p2 = 1123.0 - # => p2 = 324.0 - # x + 2 * p2 = 1447.0 - return 799.0 - - def get_guarantee_price(self, guarantee_duration): - assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id - return 240.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - return 0.0 * self.num_servers - -class DellPowerEdgeC4130(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=1) - - def get_empty_price(self): - # for c4130 on 14/10/2016 - # x + 2 x E5-2640v4 + 128G + 2 * K80 + X520 + p5years = 12281€ - # x + 2 x E5-2640v4 + 128G + 4 * K80 + X520 + p5years = 19317€ - # price of a K80 - # >>> (19317.-12281)/2 - # 3518.0 - # assuming the options cost the same as for R630 (X520=210€, p5years=240€, 128G=1778€, E5-2640v4=951€), the cost of the base system is : - # >>> 12281-951-951-1778-210-240-3518-3518 - # 1115 - # but if we integrate the X520 card so that we have a 10Gb ethernet in the base, the cost of the base system becomes : - # >>> 1115+210 - # 1325 - return 1325.0 - - def get_guarantee_price(self, guarantee_duration): - assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id - return 240.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - return 0.0 * self.num_servers - - -class DellPowerEdgeC6320(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=4) - - def get_empty_price(self): - # for 4xc6320 on 14/10/2016 - # (x: price without procs, p2603: price of e5-2603v4, p2609: price of e5-2609v4) - # x + 4 x (2 x p2620 + p32G) = 5135 € HT - # x + 4 x (2 x p2640 + p128G + pX520 + p5years) = 15590 € HT - # x + 4 x (2 x p2650 + p128G + pX520 + p5years) = 17340 € HT - # x + 4 x (2 x p2660 + p128G + pX520 + p5years) = 19490 € HT - # by examining this and the price of processors on R630 - # - E5-2620v4 : 458€ - # - E5-2640v4 : 951€ - # - E5-2650v4 : 1209€ - # - E5-2660v4 : 1525€ - # - E5-2680v4 : 1867€ - # - E5-2690v4 : 2261€ - # I could work out that : - # - the price of procs on c6320 is the price of procs on r630 * 85% - # - the price of the base c6320 with 32 Go and no proc at all is 2020.6 - # - the price of the 32G to 128G upgrade is 6222.6 euros (cheaper price of 16G->128G upgrade on r630 : (1778*4 = 7112)) - # details : - # >>> (19490.-17340)/8 - # 268.75 - # >>> (17340.-15590)/8 - # 218.75 - # >>> 218.75/258. - # 0.8478682170542635 - # >>> 268.75/316 - # 0.8504746835443038 - # >>> 15590.0+((1209.0-951.0)*0.85)*8 - # 17344.4 - # >>> 15590.0+((1525.0-951.0)*0.85)*8 - # 19493.2 - # price of 128G ram upgrade assuming that 5years guarantee costs 880€ (same as c6220), - # >>> 15590.0+((458.0-951.0)*0.85)*8-210.0*4-880.0 - 5135.0 - # 6222.6 - # >>> 5135.0 - (458.0*0.85)*8 - # 2020.6 - return 2020.6 - - def get_guarantee_price(self, guarantee_duration): - assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id - return 880.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - return 0.0 * self.num_servers - - -class DellPowerEdgeR640(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=1) - - def get_empty_price(self): - # on 29/09/2017 - # (x: price without procs, p3106: price of Bronze-3106, p6126: price of Gold6126) - # we want to know x, given dell's web site, where we can get the price for multiple proc but not 0 - # x + p3106 = 1067.0 - # x + 2 * p3106 = 1067.0 + 320.0 - # => p3106 = 320 - # => x = 1067.0 - 320.0 = 747.0 - # check if x computation is consistent with p6126 - # x + p6126 = 2767 - # x + 2 * p6126 = 4787.0 - # => p6126 = 2020.0 - # => x = 747.0 --> yes ! - return 747.0 - - def get_dimm_price(self, dimm_capacity): - return { - 8: 80.0, - 16: 160.0, - 32: 320.0, - 64: 640.0 - }[dimm_capacity] - - def get_guarantee_price(self, guarantee_duration): - if guarantee_duration > 7: - assert False, 'guarantee of more than 7 years is not available on %s' % self.host_type_id - elif guarantee_duration >= 5: - return 270.0 # from dell matinfo4 online quotation - else: - # 5-year guarantee included in base price - return 0.0 * self.num_servers - - @abstractmethod - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - # Retrait des disques de base (2x600Go 10K SAS 2.5'') : -260.0 € - # Ajout d'un disque dur 1,2 To SAS 10k Tpm 2,5" - hotplug : 165.0 € - base_disks_removal_price = -260.0 - disk_1200g_price = 165.0 - return (base_disks_removal_price + disk_1200g_price * 2) * self.num_servers - - -class DellPowerEdgeR940(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=4, num_servers=1) - - def get_empty_price(self): - # price of r940 (with 2x xeon gold 5215 and 32 Go DDR4 @ 2933GHz) on 09/06/2020 : 3784€ - # (x: price without procs, p5215: price of gold-5215, p6248: price of Gold6248) - # p6240 = 2684 - # p6248 = 3442 - # p8280l = 12075 - # x + 2 * p5215 = 3784 - # x + 4 * p6240 = 11886 => x = 1150 - # x + 4 * p6248 = 14918 => x = 1150 - # x + 4 * p8280l = 49450 => x = 1150 - # => p5215 = 1317 (agrees with proc price on r640) - return 1150.0 - - def get_dimm_price(self, dimm_capacity): - return { - 8: 80.0, - 16: 160.0, - 32: 320.0, - 64: 640.0 - }[dimm_capacity] - - def get_guarantee_price(self, guarantee_duration): - if guarantee_duration > 7: - assert False, 'guarantee of more than 7 years is not available on %s' % self.host_type_id - elif guarantee_duration >= 5: - return 630.0 # from dell matinfo4 online quotation - else: - # 5-year guarantee included in base price - return 0.0 - - @abstractmethod - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - # Retrait des disques de base (2x600Go 10K SAS 2.5'') : -260.0 € - # Ajout d'un disque dur 1,2 To SAS 10k Tpm 2,5" - hotplug : 165.0 € - base_disks_removal_price = -260.0 - disk_1200g_price = 165.0 - return (base_disks_removal_price + disk_1200g_price * 2) * self.num_servers - - -class DellPrecision3630(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=1, num_servers=1) - - def get_empty_price(self): - return 449.0 - - def get_dimm_price(self, dimm_capacity): - return { - 8: 80.0, - 16: 160.0, - 32: 320.0 - }[dimm_capacity] - - def get_guarantee_price(self, guarantee_duration): - assert guarantee_duration <= 5, 'only 5 year guarantee is handled for %s' % self.host_type_id - return 0.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - return 0.0 - -class DellPowerEdgeC6420(HostType): - - def __init__(self, host_type_id): - super().__init__(host_type_id, num_cpu_per_server=2, num_servers=4) - - def get_empty_price(self): - # for 4xc6420 on 19/06/2020 (from excel quotation) - # - # - # (x: price without procs, p2630: price of xeon gold 6230) - # x + 4 x (2 x p4210r + p48g) = 5368 € HT - # x + 4 x (2 x p6230r + p192g) = 27213 € HT - # - # p48g = 3 * 160.0 # the price of a 16G ram is 160.0 € - # p4210r = p4210r=978./2 # from r640 prices - # - - # >>> p4210r=978./2 - # >>> p6230r_upgrade = 13408.0 - # >>> p6230r_for_r640 = 2165.0 - # >>> num_servers_per_c6000 = 4 - # >>> num_cpu_per_server = 2 - # >>> p6230r_for_c6420 = (p6230r_upgrade + p4210r * (num_servers_per_c6000 * num_cpu_per_server))/(num_servers_per_c6000 * num_cpu_per_server) - # >>> p6230r_for_c6420 - # 2165.0 - - # => p4210r seems to be the same on r640 and c6420 - # - # pc6000 = 5368 - (p4210r * num_cpu_per_server + p48g) * num_servers_per_c6000 - # >>> p16g = 160.0 - # >>> p48g = p16g * 3 - # >>> pc6000 = 5368 - (p4210r * num_cpu_per_server + p48g) * num_servers_per_c6000 - # >>> pc6000 - # -464.0 - # >>> pc6000 + num_servers_per_c6000 * (p6230r_for_c6420 * num_cpu_per_server + p192g) - # Traceback (most recent call last): - # File "", line 1, in - # NameError: name 'p192g' is not defined - # >>> p192g = (192/16)*p16g - # >>> p192g - # 1920.0 - # >>> pc6000 + num_servers_per_c6000 * (p6230r_for_c6420 * num_cpu_per_server + p192g) - # 24536.0 - # >>> pc6000 + num_servers_per_c6000 * (p6230r_for_c6420 * num_cpu_per_server + p192g) + 1159 + 68 + 350 + 1100 - # 27213.0 - num_servers_per_c6000 = 4 - num_cpu_per_server = 2 - ram_price_per_gigabyte = 160.0 / 16 # 16G ram price : 160.0 € - xeon_silver_4210r_price = 978.0 / 2 # from r640 prices - basic_config_price = 5368.0 - poweredge_c6000_price = basic_config_price - (xeon_silver_4210r_price * num_cpu_per_server + ram_price_per_gigabyte * 48) * num_servers_per_c6000 - return poweredge_c6000_price - - def get_dimm_price(self, dimm_capacity): - return { - 8: 80.0, - 16: 160.0, - 32: 320.0, - 64: 640.0 - }[dimm_capacity] - - def get_guarantee_price(self, guarantee_duration): - if guarantee_duration > 7: - assert False, 'guarantee of more than 7 years is not available on %s' % self.host_type_id - elif guarantee_duration >= 5: - return 1100.0 # from c6420-20200716-price - else: - # 5-year guarantee included in base price - return 0.0 - - def get_disk_upgrade_price(self, asked_disk_capacity): - assert 1.9e12 < asked_disk_capacity < 2.1e12, 'only 2To upgrades are handled for %s' % self.host_type_id - # from c6420-20200716-price - # | Ajout d'un disque dur 1 To SATA 7200 Tpm 3,5'' pour les 4 serveurs | | 4-3-1-14g096 | C6420 | 361 € | | € - | - return 361.0 - -def create_host_type(host_type_id): - if host_type_id == 'c6420': - return DellPowerEdgeC6420(host_type_id) - if host_type_id == 'c6320': - return DellPowerEdgeC6320(host_type_id) - if host_type_id == 'c4130': - return DellPowerEdgeC4130(host_type_id) - if host_type_id == 'r620': - return DellPowerEdgeR620(host_type_id) - if host_type_id == 'r630': - return DellPowerEdgeR630(host_type_id) - if host_type_id == 'r640': - return DellPowerEdgeR640(host_type_id) - if host_type_id == 'r940': - return DellPowerEdgeR940(host_type_id) - if host_type_id == 'precision3630': - return DellPrecision3630(host_type_id) - assert False - -class Config(): - - def __init__(self, host_type_id): - self.host_type = create_host_type(host_type_id) - - def get_empty_price(self): - return self.host_type.get_empty_price() - - def get_ram_update_price(self, cpu, ram_per_core=None, ram_per_server=None, ram_per_cpu=None): - - # ramUpgradePrice128Gb = { - # 'c6220':3520.0, - # 'r620':2010.0, - # 'r630':1778.0, - # 'r640':1780.0, - # 'r730':1778.0, - # 'r940':960.0, # 32 Gb 2933 MHz RDIMM : 320 € - # 'c6320':6222.6, - # 'c4310':1778.0, - # 'precision3630': 1536.0 } - if ram_per_cpu: - assert not ram_per_core - assert not ram_per_server - if ram_per_core: - assert not ram_per_server - assert not ram_per_cpu - ram_per_cpu = cpu.num_cores * ram_per_core - if ram_per_server: - assert not ram_per_core - assert not ram_per_cpu - ram_per_cpu = ram_per_server / self.num_cpu_per_server - - ram_per_channel = ram_per_cpu / cpu.num_ram_channels - dimm_capacity = None - if ram_per_channel > 64.0e9: - assert False, 'ram_per_channel is too big (%f bytes > 64 Gb)' % ram_per_channel - elif ram_per_channel > 32.0e9: - dimm_capacity = 64 - elif ram_per_channel > 16.0e9: - dimm_capacity = 32 - elif ram_per_channel > 8.0e9: - dimm_capacity = 16 - elif ram_per_channel > 4.0e9: - dimm_capacity = 8 - else: - try: - self.host_type.get_dimm_price(4) - dimm_capacity = 4 - except: - # 4Gb dimms are not available, use 8 Gb instead - dimm_capacity = 8 - # print('warning : forcing dimm capacity to 16G !!!!!!') - # dimm_capacity = 16 - ram_price = self.num_servers * self.num_cpu_per_server * cpu.num_ram_channels * self.host_type.get_dimm_price(dimm_capacity) - print("ram_price : %f € for %d dimms of %d Gb" % (ram_price, self.num_servers * self.num_cpu_per_server * cpu.num_ram_channels, dimm_capacity)) - return ram_price - - def get_guarantee_price(self, guarantee_duration): - return self.host_type.get_guarantee_price(guarantee_duration) - - def get_disk_upgrade_price(self, asked_disk_capacity): - return self.host_type.get_disk_upgrade_price(asked_disk_capacity) - - @property - def num_servers(self): - return self.host_type.num_servers - - @property - def num_cpu_per_server(self): - return self.host_type.num_cpu_per_server - - - -def plotSystemEfficiency(): - - cpuTable = numpy.genfromtxt('cpu_table.dat', dtype=("|U15", float, int, float, float, float), names=True, delimiter='\t') - #cpuTable = numpy.genfromtxt('dell_ivybridge_table.dat', dtype=(('id', "|S10"), ('clock', float), ('num_cores', int), ('price', float, float)), names=None, delimiter='\t') - print(type(cpuTable)) - print(cpuTable.dtype) - print(cpuTable) - print(cpuTable['id']) - - dellPriceTable = numpy.genfromtxt('dell_procoptions_table.dat', dtype=("|U15", "|U15", float), names=True, delimiter='\t') - #cpuTable = numpy.genfromtxt('dell_ivybridge_table.dat', dtype=(('id', "|S10"), ('clock', float), ('num_cores', int), ('price', float, float)), names=None, delimiter='\t') - - #for (x, y) in clusters: - serverBasePowerConsumption = 100.0 # rough estimation in watts - def GHzToMHz( frequency ): - return frequency * 1000.0 - - kWHPrice = 0.07 * 1.5 - containerLifetime = 7.0 # in years - powerUsageEfficiency = 0.5 - - - - def getColorCodeFromItemLabel(label): - generation=label[-1] - (model, proc_id) = 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 - }[get_proc_architecture(proc_id)] - # 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 = { - 'r620': 0.6, - 'r630': 0.6, - 'r640': 0.6, - 'c4310': 0.6, - 'r730': 0.4, - 'r940': 0.8, - 'c6220': 1.0, - 'c6320': 1.0, - 'c6420': 1.0, - 'precision3630': 0.2 - }[model] - value = 0.9 - return matplotlib.colors.hsv_to_rgb((hue, saturation, value)) - - def get_marker_from_label(label): - (model, proc_id) = re.split('_', label) - return get_marker(proc_id) - - - itemPrice = numpy.array([]) - itemPowerConsumption = numpy.array([]) - itemSpeed = numpy.array([]) - itemLabel = numpy.array([]) - itemGeneration = numpy.array([]) - for hostTypeId, procId, procOptionPrice in zip(dellPriceTable['host_type_id'], dellPriceTable['proc_id'], dellPriceTable['proc_option_price']): - print(hostTypeId, procId) - #if hostTypeId == 'r630': - # continue - cpu = Cpu(procId) - if not cpu.architecture in ['coffeelake', 'skylake','cascadelake']: - continue - - config = Config(hostTypeId) - - itemGeneration = procId[-1] - - itemLabel = numpy.append( itemLabel, hostTypeId + '_' + procId ) - print('procOptionPrice', procOptionPrice) - config_price = procOptionPrice - config_price += config.get_empty_price() - print('config.get_empty_price()', config.get_empty_price()) - ram_update_price = config.get_ram_update_price(cpu=cpu, ram_per_core=6.0e9) - # ram_update_price = config.get_ram_update_price(cpu=cpu, ram_per_server=192.0e9) - # ram_update_price = config.get_ram_update_price(cpu=cpu, ram_per_cpu=96.0e9) - print('ram_update_price', ram_update_price) - config_price += ram_update_price - config_price += config.get_guarantee_price(5) - print('config.config.get_guarantee_price(5)', config.get_guarantee_price(5)) - config_price += config.get_disk_upgrade_price(2.0e12) - print('config.get_disk_upgrade_price(2.0e12)', config.get_disk_upgrade_price(2.0e12)) - itemPrice = numpy.append( itemPrice, config_price ) - itemPowerConsumption = numpy.append( itemPowerConsumption, (cpu.tdp * config.num_cpu_per_server+serverBasePowerConsumption) * config.num_servers ) - # print(hostTypeId, procId, itemPowerConsumption[-1]) - itemSpeed = numpy.append( itemSpeed, cpu.num_dp_flop_per_cycle * cpu.clock * 1.e9 * cpu.num_cores * config.num_cpu_per_server * config.num_servers) - - #pylab.plot(x, y, '+') - #pylab.xlabel('speed/price ratio [core.MHz/euros]') - #pylab.ylabel('speed/power consumption ratio [core.MHz/W]') - #pylab.show() # or savefig() - - - #print("items = ") - #print(itemLabel) - - markerSize = 50 - - if False: - plt.subplot(1,2,1) - plt.subplots_adjust(bottom = 0.1) - markersCycler = itertools.cycle(itertools.product(markerTypes, markerColors)) - x = itemSpeed / itemPrice - y = itemSpeed / itemPowerConsumption - for label, x1, y1, power, speed, price, in zip(itemLabel, x, y, itemPowerConsumption, itemSpeed, itemPrice): - marker = markersCycler.next() - color = getColorCodeFromItemLabel(label) - plt.scatter( x1, y1, color = color, s = markerSize, marker = marker[0], label = label) - #print(x1, y1, color, markerSize, marker[0], label) - if False: - plt.scatter( x, y, marker = 'o') - for label, x1, y1, power, speed, price, in zip(itemLabel, x, y, itemPowerConsumption, itemSpeed, itemPrice): - #print(label) - plt.annotate( u'%s (%.1f core.GHz, %.0f W, %.0f €)' % (label,speed/1000.0, power, price), - xy = (x1, y1), xytext = (-50, 50), - textcoords = 'offset points', ha = 'right', va = 'bottom', - bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5), - arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0')) - plt.xlabel(u'speed/price ratio [core.MHz/€]') - plt.ylabel(u'speed/power consumption ratio [core.MHz/W]') - plt.xlim( xmin = 0.0 ) - plt.ylim( ymin = 0.0 ) - - plt.subplot(1,2,1) - #fig = plt.figure() - #ax = fig.gca() - #ax.set_xticks(numpy.arange(0,1,0.1)) - #ax.set_yticks(numpy.arange(0,1.,0.1)) - - powerUsedInLifetime = (itemPowerConsumption * containerLifetime * 365 * 24) / powerUsageEfficiency - itemTotalCost = itemPrice + (powerUsedInLifetime / 1000.0 * kWHPrice ) - markersCycler = itertools.cycle(itertools.product(markerTypes, markerColors)) - item_flops = itemSpeed - # print item_flops - item_total_num_ops = item_flops * containerLifetime * 365 * 24 * 3600 - # print(itemPrice) - x = itemPrice - y = item_total_num_ops / itemTotalCost - for i in range(len(itemLabel)): - print(itemLabel[i], itemPrice[i], y[i]) - print('itemTotalCost', itemTotalCost[i]) - print('flops', item_flops[i]) - # print y - for label, x1, y1, power, speed, price, in zip(itemLabel, x, y, itemPowerConsumption, itemSpeed, itemPrice): - if y1 > 0.0001: - color = getColorCodeFromItemLabel(label) - # marker = markersCycler.next() - marker = get_marker_from_label( label ) - #print(x1, y1) - plt.scatter( x1, y1, facecolors = color, s = markerSize, marker = marker[0], label = label) - if y1 > 5.0e16: - plt.annotate( u'%s' % 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')) - - plt.xlabel(u'purchase price [€]') - plt.ylabel(u'num total DP operations/total cost [€/^-1]') - plt.title(u'total cost including electricity') - 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() - -#plotCpuPassmark(): -plotSystemEfficiency() diff --git a/rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html b/rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html new file mode 100644 index 0000000..eb72e5f --- /dev/null +++ b/rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html @@ -0,0 +1,604 @@ + + + + + + + rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell + + + + + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ +
+ +
+
+
+ + + + +
+ +
+
+
+ +
+ +
+Cat2 Conf4 PowerEdge R640
+ +
+ +
+
+ + + +
+
+ + +
+ +
+ +
+
+

Avec son architecture à double socket +1U, le PowerEdge R640 est la plate-forme idéale pour vos opérations de +calcul sur des datacenters scale-out haute densité. Le R640 combine +densité, performances et évolutivité pour optimiser les performances de +vos applications et la densité de votre datacente. 

+ +
+ + + +
+
+ +
+ + + + + +
+
+ +
+
+
+
+ + + +
+
+ + + +
+
+ + + +
Configuration
0.00 €
Base
PowerEdge R640
0.00 €
PowerEdge R640
0.00 €
Processeurs (Passage)
Processeur Intel Xeon Silver 4208 2.1GHz,11M Cache,9.60GT/s, 2UPI,No Turbo, HT,8C/16T (85W) - DDR4-2400
0.00 €
Passage à processeur Intel Xeon Gold 6240L 2.6GHz, 24.75M Cache,10.40GT/s, 2UPI, Turbo, HT,18C/36T (150W) - DDR4-2933
+ 4551.00 €
Passage à processeur Intel Xeon Gold 6234 3.3GHz, 24.75M Cache,10.40GT/s, 3UPI, Turbo, HT,8C/16T (130W) - DDR4-2933
+ 2061.00 €
Passage à processeur Intel Xeon Gold 6238L 2.1GHz, 30.25M Cache,10.40GT/s, 3UPI, Turbo, HT,22C/44T (140W) - DDR4-2933
+ 4871.00 €
Processeur Intel Xeon Silver 4208 2.1GHz,11M Cache,9.60GT/s, 2UPI,No Turbo, HT,8C/16T (85W) - DDR4-2400
0.00 €
Passage à processeur Intel Xeon Silver 4214Y 2.2GHz, 16.5M Cache,9.60GT/s, 2UPI, Turbo, HT,12C/24T (85W) - DDR4-2400
+ 396.00 €
Passage à processeur Intel Xeon Gold 5215L 2.5GHz, 13.75M Cache,10.40GT/s, 2UPI, Turbo, HT,10C/20T (85W) - DDR4-2400
+ 3146.00 €
Passage + à processeur Intel Xeon Gold 6210U 2.5GHz, 27.5M Cache,10.40GT/s, 3UPI, + Turbo, HT,20C/40T (150W) - DDR4-2933 / 1 CPU Maximum
+ 1271.00 €
Passage + à processeur Intel Xeon Gold 6212U 2.4GHz, 35.75M Cache,10.40GT/s, +3UPI, Turbo, HT,24C/48T (165W) - DDR4-2933 / 1 CPU Maximum
+ 1871.00 €
Passage à processeur Intel Xeon Platinium 8268 2.9GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (205W) - DDR4-2933
+ 5576.00 €
Passage à processeur Intel Xeon Gold 6254 3.1GHz, 24.75M Cache,10.40GT/s, 2UPI, Turbo, HT,18C/36T (200W) - DDR4-2933
+ 3541.00 €
Passage à processeur Intel Xeon Gold 5217 3GHz, 11M Cache,10.40GT/s, 2UPI, Turbo, HT,8C/16T (115W) - DDR4-2666
+ 1221.00 €
Passage à processeur Intel Xeon Gold 5215 2.5GHz, 13.75M Cache,10.40GT/s, 2UPI, Turbo, HT,10C/20T (85W) - DDR4-2400
+ 888.00 €
Passage à processeur Intel Xeon Silver 4216 2.1GHz, 22M Cache,9.60GT/s, 2UPI, Turbo, HT,16C/32T (100W) - DDR4-2400
+ 579.00 €
Passage à processeur Intel Xeon Gold 6240Y 2.6GHz, 24.75M Cache,10.40GT/s, 2UPI, Turbo, HT,18C/36T (150W) - DDR4-2933
+ 2521.00 €
Passage à processeur Intel Xeon Platinium 8260 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 4310.00 €
Passage à processeur Intel Xeon Platinium 8276 2.2GHz, 38.5M Cache,10.40GT/s, 2UPI, Turbo, HT,28C/56T (165W) - DDR4-2933
+ 8549.00 €
Passage à processeur Intel Xeon Gold 5222 3.8GHz, 16.5M Cache,10.40GT/s, 2UPI, Turbo, HT,4C/8T (105W) - DDR4-2933
+ 838.00 €
Passage à processeur Intel Xeon Platinium 8260L 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 6241.00 €
Passage à processeur Intel Xeon Gold 6244 3.6GHz, 24.75M Cache,10.40GT/s, 3UPI, Turbo, HT,8C/16T (150W) - DDR4-2933
+ 2961.00 €
Passage à processeur Intel Xeon Platinium 8260Y 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 4871.00 €
Passage à processeur Intel Xeon Gold 6252 2.1GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (150W) - DDR4-2933
+ 3631.00 €
Passage à processeur Intel Xeon Platinium 8270 2.7GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,26C/52T (205W) - DDR4-2933
+ 7083.00 €
Passage à processeur Intel Xeon Platinium 8253 2.2GHz, 22M Cache,10.40GT/s, 3UPI, Turbo, HT,16C/32T (125W) - DDR4-2933
+ 2933.00 €
Passage à processeur Intel Xeon Gold 6258R 2,7GHz, 38.5M Cache,10.40GT/s, 2UPI, Turbo, HT,28C/56T (205W) - DDR4-2933
+ 3971.00 €
Passage à processeur Intel Xeon Gold 6242R 3,1GHz, 35,75M Cache,10.40GT/s, 2UPI, Turbo, HT,20C/40T (205W) - DDR4-2933
+ 2421.00 €
Passage à processeur Intel Xeon Gold 6246R 3.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,16C/32T (205W) - DDR4-2933
+ 3146.00 €
Passage à processeur Intel Xeon Gold 6240R 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 2255.00 €
Passage à processeur Intel Xeon Gold 6238R 2.2GHz, 38.5M Cache,10.40GT/s,Turbo, HT,28C/56T (165W) - DDR4-2933
+ 2521.00 €
Passage à processeur Intel Xeon Gold 6230R 2.1GHz, 35,75M Cache,10.40GT/s, Turbo, HT,26C/52T (150W) - DDR4-2933
+ 1736.00 €
Passage à processeur Intel Xeon Gold 5218R 2.1GHz, 27,5M Cache,10.40GT/s, 2UPI, Turbo, HT,20C/40T (125W) - DDR4-2666
+ 908.00 €
Passage à processeur Intel Xeon Silver 4215R 3,2GHz, 11M Cache,9.60GT/s, 2UPI, Turbo, HT,8C/16T (130W) - DDR4-2400
+ 421.00 €
Passage à processeur Intel Xeon Gold 5220R 2.2GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (150W) - DDR4-2666
+ 1247.00 €
Passage à processeur Intel Xeon Silver 4214R 2.4GHz, 16.5M Cache,9.60GT/s, 2UPI, Turbo, HT,12C/24T (100W) - DDR4-2400
+ 280.00 €
Passage à processeur Intel Xeon Silver 4210R 2.4GHz,13.75M Cache,9.60GT/s, 2UPI, Turbo, HT,10C/20T (100W) - DDR4-2400
+ 60.00 €
Passage à processeur Intel Xeon Gold 6248R 3GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (205W) - DDR4-2933
+ 3013.00 €
Passage à processeur Intel Xeon Gold 6226R 2,9GHz, 22M Cache,10.40GT/s,Turbo, HT,16C/32T (150W) - DDR4-2933
+ 1121.00 €
Processeurs additionnels
Pas de processeur supplémentaire
0.00 €
Processeur additionnel Intel Xeon Gold 6240L 2.6GHz, 24.75M Cache,10.40GT/s, 2UPI, Turbo, HT,18C/36T (150W) - DDR4-2933
+ 4980.00 €
Processeur additionnel Intel Xeon Gold 6234 3.3GHz, 24.75M Cache,10.40GT/s, 3UPI, Turbo, HT,8C/16T (130W) - DDR4-2933
+ 2490.00 €
Processeur additionnel Intel Xeon Gold 6238L 2.1GHz, 30.25M Cache,10.40GT/s, 3UPI, Turbo, HT,22C/44T (140W) - DDR4-2933
+ 5300.00 €
Processeur additionnel Intel Xeon Silver 4208 2.1GHz,11M Cache,9.60GT/s, 2UPI, Turbo, HT,8C/16T (85W) - DDR4-2400
+ 429.00 €
Processeur additionnel Intel Xeon Silver 4214Y 2.2GHz, 16.5M Cache,9.60GT/s, 2UPI, Turbo, HT,12C/24T (85W) - DDR4-2400
+ 825.00 €
Processeur additionnel Intel Xeon Gold 5215L 2.5GHz, 13.75M Cache,10.40GT/s, 2UPI, Turbo, HT,10C/20T (85W) - DDR4-2400
+ 3575.00 €
Pas de processeur supplémentaire
0.00 €
Processeur additionnel Intel Xeon Platinium 8268 2.9GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (205W) - DDR4-2933
+ 6005.00 €
Processeur additionnel Intel Xeon Gold 6254 3.1GHz, 24.75M Cache,10.40GT/s, 2UPI, Turbo, HT,18C/36T (200W) - DDR4-2933
+ 3970.00 €
Processeur additionnel Intel Xeon Gold 6240Y 2.6GHz, 24.75M Cache,10.40GT/s, 2UPI, Turbo, HT,18C/36T (150W) - DDR4-2933
+ 2950.00 €
Processeur additionnel Intel Xeon Platinium 8260 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 4739.00 €
Processeur additionnel Intel Xeon Platinium 8276 2.2GHz, 38.5M Cache,10.40GT/s, 2UPI, Turbo, HT,28C/56T (165W) - DDR4-2933
+ 8978.00 €
Processeur additionnel Intel Xeon Gold 5222 3.8GHz, 16.5M Cache,10.40GT/s, 2UPI, Turbo, HT,4C/8T (105W) - DDR4-2933
+ 1267.00 €
Processeur additionnel Intel Xeon Platinium 8260L 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 6670.00 €
Processeur additionnel Intel Xeon Silver 4216 2.1GHz, 22M Cache,9.60GT/s, 2UPI, Turbo, HT,16C/32T (100W) - DDR4-2400
+ 1008.00 €
Processeur additionnel Intel Xeon Gold 5215 2.5GHz, 13.75M Cache,10.40GT/s, 2UPI, Turbo, HT,10C/20T (85W) - DDR4-2400
+ 1317.00 €
Processeur additionnel Intel Xeon Gold 6244 3.6GHz, 24.75M Cache,10.40GT/s, 3UPI, Turbo, HT,8C/16T (150W) - DDR4-2933
+ 3390.00 €
Processeur additionnel Intel Xeon Gold 6252 2.1GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (150W) - DDR4-2933
+ 4060.00 €
Processeur additionnel Intel Xeon Gold 5217 3GHz, 11M Cache,10.40GT/s, 2UPI, Turbo, HT,8C/16T (115W) - DDR4-2666
+ 1650.00 €
Processeur additionnel Intel Xeon Platinium 8260Y 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 5300.00 €
Processeur additionnel Intel Xeon Platinium 8253 2.2GHz, 22M Cache,10.40GT/s, 3UPI, Turbo, HT,16C/32T (125W) - DDR4-2933
+ 3362.00 €
Processeur additionnel Intel Xeon Platinium 8270 2.7GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,26C/52T (205W) - DDR4-2933
+ 7512.00 €
Processeur additionnel Intel Xeon Gold 6258R 2,7GHz, 38.5M Cache,10.40GT/s, 2UPI, Turbo, HT,28C/56T (205W) - DDR4-2933
+ 4400.00 €
Processeur additionnel Intel Xeon Gold 6242R 3,1GHz, 35,75M Cache,10.40GT/s, 2UPI, Turbo, HT,20C/40T (205W) - DDR4-2933
+ 2850.00 €
Processeur additionnel Intel Xeon Gold 6246R 3.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,16C/32T (205W) - DDR4-2933
+ 3575.00 €
Processeur additionnel Intel Xeon Gold 6240R 2.4GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (165W) - DDR4-2933
+ 2684.00 €
Processeur additionnel Intel Xeon Gold 6238R 2.2GHz, 38.5M Cache,10.40GT/s,Turbo, HT,28C/56T (165W) - DDR4-2933
+ 2950.00 €
Processeur additionnel Intel Xeon Gold 6230R 2.1GHz, 35,75M Cache,10.40GT/s, Turbo, HT,26C/52T (150W) - DDR4-2933
+ 2165.00 €
Processeur additionnel Intel Xeon Gold 6226R 2,9GHz, 22M Cache,10.40GT/s,Turbo, HT,16C/32T (150W) - DDR4-2933
+ 1550.00 €
Processeur additionnel Intel Xeon Gold 5218R 2.1GHz, 27,5M Cache,10.40GT/s, 2UPI, Turbo, HT,20C/40T (125W) - DDR4-2666
+ 1300.00 €
Processeur additionnel Intel Xeon Silver 4215R 3,2GHz, 11M Cache,9.60GT/s, 2UPI, Turbo, HT,8C/16T (130W) - DDR4-2400
+ 810.00 €
Processeur additionnel Intel Xeon Gold 5220R 2.2GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (150W) - DDR4-2666
+ 1676.00 €
Processeur additionnel Intel Xeon Silver 4214R 2.4GHz, 16.5M Cache,9.60GT/s, 2UPI, Turbo, HT,12C/24T (100W) - DDR4-2400
+ 709.00 €
Processeur additionnel Intel Xeon Silver 4210R 2.4GHz,13.75M Cache,9.60GT/s, 2UPI, Turbo, HT,10C/20T (100W) - DDR4-2400
+ 489.00 €
Processeur additionnel Intel Xeon Gold 6248R 3GHz, 35.75M Cache,10.40GT/s, 2UPI, Turbo, HT,24C/48T (205W) - DDR4-2933
+ 3442.00 €
Mémoires (Passage)
Mémoire 16 Go DDR4 à 2933MHz (1x16Go)
0.00 €
Mémoire 16 Go DDR4 à 2933MHz (1x16Go)
0.00 €
Passage à 32Go DDR4 en 4 x 8Go 2667 Mhz RDIMM (A partir de la base en 1x16Go)
+ 160.00 €
Passage à 32Go DDR4 en 1 x 32Go 2933 Mhz RDIMM (A partir de la base en 1x16Go)
+ 160.00 €
Passage à 64Go DDR4 en 1 x 64Go 2933 Mhz RDIMM (A partir de la base en 1x16Go)
+ 480.00 €
Passage à 128Go DDR4 en 1 x 128Go 2667 Mhz LRDIMM (A partir de la base en 1x16Go)
+ 2890.00 €
Mémoire: Ajout de barettes additionnelles
VEUILLEZ SAISIR ICI VOS BARETTES ADDITIONNELLES
0.00 €
VEUILLEZ SAISIR ICI VOS BARETTES ADDITIONNELLES
0.00 €
Optane DC Persistent Memory - 128Go 2666Mhz
+ 460.00 €
Ajout d'une barette de 128Go 2667 Mhz LRDIMM
+ 3050.00 €
Ajout d'une barette de 8Go 2667 Mhz RDIMM
+ 80.00 €
Ajout d'une barette de 16Go 2933 Mhz RDIMM
+ 160.00 €
Ajout d'une barette de 32Go 2933 Mhz RDIMM
+ 320.00 €
Ajout d'une barette de 64Go 2933 Mhz RDIMM
+ 640.00 €
Configuration du châssis
Châssis 2,5" avec jusqu’à 8 disques durs et 3 emplacements PCIe
0.00 €
Passage au châssis 3,5" pour maximum 4 disques Hot Plugs
0.00 €
Châssis 2,5" avec jusqu’à 8 disques durs et 3 emplacements PCIe
0.00 €
Passage au châssis 2,5" pour maximum 10 disques Hot Plugs
+ 90.00 €
Passage au châssis 2,5" pour maximum 10 disques Hot Plugs + 2 disques 2.5'' hot-plug à l'arrière avec 1 slots PCIE
+ 130.00 €
Passage + au châssis 2,5" pour maximum 10 disques Hot Plugs avec 8 emplacements +disques NVME (2 CPU Obligatoire) avec 3 slots PCIE - Au moins 1 disque +obligatoire
+ 150.00 €
Contrôleur RAID
PERC H330 Contrôleur Raid
0.00 €
PERC H330 Contrôleur Raid
0.00 €
Passage à carte HBA330 pour configuration sans Raid
0.00 €
Passage à carte RAID H740p avec 8 Go NV Cache
+ 319.00 €
Passage à carte RAID H730p avec 2 Go NV Cache
+ 196.00 €
Disques durs (Passage)
2 disques durs 1,2To 10 000 tr/mn SAS
0.00 €
2 disques durs 1,2To 10 000 tr/mn SAS
0.00 €
Retrait des disques de base (2x1.2To SAS 10Ktpm 2.5'')
-330.00 €
Disques M.2 (BOSS)
0.00 €
Ajout d'un contrôleur BOSS et 1 carte M.2 de 240Go
+ 219.00 €
Ajout d'un contrôleur BOSS et 2 cartes M.2 de 240Go
+ 364.00 €
Ajout d'un contrôleur BOSS et 1 carte M.2 de 480Go
+ 389.00 €
Ajout d'un contrôleur BOSS et 2 cartes M.2 de 480Go
+ 683.00 €
Disques durs additionnels
VEUILLEZ SAISIR ICI VOS DISQUES ADDITIONNELS EN TENANT COMPTE DES LIMITES IMPOSEES PAR LE CHASSIS CHOISI
0.00 €
VEUILLEZ SAISIR ICI VOS DISQUES ADDITIONNELS EN TENANT COMPTE DES LIMITES IMPOSEES PAR LE CHASSIS CHOISI
0.00 €
Ajout d'un disque dur 480 Go SSD SAS Mix Use - TOSHIBA PM5-V 2,5" - 3DWPD - 2628TBW
+ 489.00 €
Ajout d'un disque dur 3.84To SSD SAS Mix Use - 2,5" - 3DWPD - 21024TBW
+ 1850.00 €
Ajout d'un disque dur 480 Go SSD SATA Read Intensive - 2.5" - 1DWPD - 876TBW
+ 175.00 €
Ajout d'un disque dur 480 Go SSD SATA Mix Use - 2.5" - 3DWPD - 2628TBW
+ 230.00 €
Ajout d'un disque dur 800 Go SSD SAS Mix Use - 2.5'' - 3DWPD - 4360TBW
+ 450.00 €
Ajout d'un disque dur 960 Go SSD SATA Read Intensive - 2.5" - 1DWPD - 1752TBW
+ 330.00 €
Ajout d'un disque dur 960 Go SSD SATA Mix Use - 2.5" - 3DWPD - 5256TBW
+ 430.00 €
Ajout d'un disque dur 960 Go SSD SAS Read Intensive - 2,5" - 1DWPD - 1752TBW
+ 500.00 €
Ajout d'un disque dur 1.6 To SSD SAS Mix Use - 2,5" - 3DWPD - 8760TBW
+ 800.00 €
Ajout d'un disque dur 1.92 To SSD SATA Read Intensive - 2.5" - 1DWPD - 3504TBW
+ 600.00 €
Ajout d'un disque dur 1.92 To SSD SATA Mix Use - 2.5" - 3DWPD - 10512TBW
+ 850.00 €
Ajout d'un disque dur 1.92 To SSD SAS Read Intensive - 2,5" - 1DWPD - 3504TBW
+ 780.00 €
Ajout d'un disque dur 3.84 To SSD SATA Read Intensive - 2.5" - 1DWPD - 7008TBW
+ 1250.00 €
Ajout d'un disque dur 3.84 To SSD SAS Read Intensive - 2,5" - 1DWPD - 7008TBW
+ 1550.00 €
Ajout d'un disque dur 300 Go SAS 15k Tpm 2,5" - hotplug
+ 150.00 €
Ajout d'un disque dur 600 Go SAS 10k Tpm 2,5" - hotplug
+ 130.00 €
Ajout d'un disque dur 600 Go SAS 15k Tpm 2,5" - hotplug
+ 180.00 €
Ajout d'un disque dur 900 Go SAS 15k Tpm 2,5" - hotplug
+ 280.00 €
Ajout d'un disque dur 1,2 To SAS 10k Tpm 2,5" - hotplug
+ 165.00 €
Ajout d'un disque dur 1,8 To SAS 10k Tpm 2,5" - hotplug
+ 240.00 €
Ajout d'un disque dur 2 To Nearline SAS 7200 Tpm 3,5"- hotplug
+ 145.00 €
Ajout d'un disque dur 4 To Nearline SAS 7200 Tpm 3,5"- hotplug
+ 180.00 €
Ajout d'un disque dur 8 To Nearline SAS 7200 Tpm 3,5"- hotplug
+ 280.00 €
Ajout d'un disque dur 2.4 To SAS 10k Tpm 2,5" - hotplug
+ 350.00 €
Ajout d'un disque dur 12 To Nearline SAS 7200 Tpm 3,5"- hotplug
+ 420.00 €
Ajout d'un disque dur 1.6 To SSD SAS Write Intensive - TOSHIBA PM5-M 2,5" - 10DWPD - 29200TBW
+ 1800.00 €
Ajout d'un disque dur 400 Go SSD SAS Write Intensive - TOSHIBA PM5-M 2,5" - 10DWPD - 7300TBW
+ 700.00 €
Ajout d'un disque dur 800 Go SSD SAS Write Intensive - TOSHIBA PM5-M 2,5" - 10DWPD - 14600TBW
+ 1200.00 €
Ajout d'un disque dur 240 Go SSD SATA Mix Use - INTEL S4610 2.5" - 3DWPD - 1314TBW
+ 170.00 €
Ajout d'un disque dur 14 To Nearline SAS 7200 Tpm 3,5"- hotplug
+ 530.00 €
Ajout d'un disque dur 16 To Nearline SAS 7200 Tpm 3,5"- hotplug
+ 610.00 €
Lecteur optique (ajout)
Pas de lecteur optique intégré
0.00 €
Pas de lecteur optique intégré
0.00 €
Lecteur/Graveur DVD
+ 20.00 €
Module SD interne
0.00 €
Ajout de 2 cartes SD (MicroSDHC/SDXC) de 16Go redondantes pour hyperviseur
+ 50.00 €
Ajout de 2 cartes SD (MicroSDHC/SDXC) de 32Go redondantes pour hyperviseur
+ 95.00 €
Ajout de 2 cartes SD (MicroSDHC/SDXC) de 64Go redondantes pour hyperviseur
+ 219.00 €
Disques NVME
0.00 €
Ajout d'un disque NVME 2.5'' INTEL P4510 1 To Read Intensive
+ 460.00 €
Ajout d'un disque NVME 2.5'' INTEL P4610 3.2 To Mix Use
+ 2200.00 €
Ajout d'un disque NVME 2.5'' INTEL P4610 1.6 To Mix Use
+ 1100.00 €
Ajout d'un disque NVME 2.5'' INTEL P4610 6.4 To Mix Use
+ 4400.00 €
Ajout d'un disque NVME 2.5'' Samsung PM1725 1.6 To Mix Use
+ 1100.00 €
Ajout d'un disque NVME 2.5'' Samsung PM1725 3.2 To Mix Use
+ 2200.00 €
Ajout d'un disque NVME 2.5'' Samsung PM1725 6.4 To Mix Use
+ 4400.00 €
Carte de montage PCIe
Carte de montage Configuration 4, 2 emplacements x16 profil bas
0.00 €
Carte de montage Configuration 4, 2 emplacements x16 profil bas
0.00 €
Cartes réseau intégrées
Broadcom 5720 Quatre ports 1Gb Carte réseau
0.00 €
Passage à carte réseau Broadcom 57414 2 ports 25Gb SFP28
+ 290.00 €
Passage à carte réseau Broadcom 57416 2 ports 10Gb Base-T et Broadcom 5720 2 ports 1Gb Base-T
+ 140.00 €
Broadcom 5720 Quatre ports 1Gb Carte réseau
0.00 €
Passage à carte réseau Intel X710 quatre ports 10 GB SFP+
+ 330.00 €
Passage à carte réseau Intel X710 double ports 10 GB SFP+ et i350 double ports gigabit
+ 259.00 €
Passage à carte réseau Intel X550 quatre ports 10 GB Base-T
+ 290.00 €
Passage à carte réseau Intel X550 double ports 10 GB Base-T et i350 double ports gigabit
+ 145.00 €
Passage à carte réseau Intel i350 quatre ports gigabit
+ 130.00 €
Passage à carte réseau Mellanox Connect-X 4 Dual Ports 25Gbits SFP
+ 314.00 €
Passage carte réseau QLogic 41164 Quad Ports 10GbE SFP+
+ 210.00 €
Passage carte réseau QLogic 41164 Quad Ports 10GbE Base-T
+ 254.00 €
Passage carte réseau QLogic 41262 Dual Ports 25GbE SFP28
+ 160.00 €
Passage carte réseau QLogic 41162 Dual Ports 10GbE Base-T et Dual ports 1G RJ45
+ 154.00 €
Passage carte réseau QLogic 41264 Dual Ports 10GbE SFP+ et Dual ports 1G RJ45
+ 140.00 €
Adaptateur de bus hôte/Carte réseau convergé
0.00 €
Ajout carte HBA FC Emulex LPE 31002-M6 double port 16 Gb
+ 654.00 €
Ajout carte HBA FC Emulex LPE 31000-M6 mono port 16 Gb
+ 449.00 €
Ajout carte HBA FC Emulex LPE 12002 double port 8 Gb
+ 449.00 €
Ajout carte HBA FC Emulex LPE 12000 mono port 8 Gb
+ 322.00 €
Ajout carte HBA FC Qlogic 2742 double port 32Gb
+ 1137.00 €
Ajout carte HBA FC Qlogic 2692 double port 16Gb
+ 650.00 €
Ajout carte HBA FC Qlogic 2690 mono port 16Gb
+ 439.00 €
Ajout carte HBA FC Qlogic 2562 double port 8Gb
+ 389.00 €
Ajout carte HBA FC Qlogic 2560 mono port 8Gb
+ 276.00 €
Ajout carte HBA FC Emulex LPE 35000 double port 32 Gb
+ 950.00 €
Cartes PCIe supplémentaires
0.00 €
Ajout carte RAID H840 8Go Nvram avec sortie externe pour connexion à baie Powervault MD1400
+ 350.00 €
Ajout carte SAS 12Gb/s HBA Externe 2 ports
+ 85.00 €
Carte réseau supplémentaire
0.00 €
Ajout carte Broadcom 57414 25G SFP Dual Ports
+ 205.00 €
Ajout carte Broadcom 57416 10G Base-T Dual Ports
+ 190.00 €
Ajout carte Broadcom 57412 10G SFP+ Dual Ports
+ 180.00 €
Ajout carte réseau Broadcom 5719 quatre ports gigabit
+ 66.00 €
Ajout carte réseau Broadcom 5720 deux ports gigabit
+ 48.00 €
Ajout carte réseau Intel X710 quatre ports 10 GB Base-T
+ 394.00 €
Ajout carte réseau Intel X710 deux ports 10 GB SFP+
+ 290.00 €
Ajout carte réseau Intel X550 deux ports 10 Gb Base-T
+ 200.00 €
Ajout carte réseau Intel I350 quatre ports gigabit
+ 141.00 €
Ajout carte réseau Intel I350 deux ports gigabit
+ 65.00 €
Intel® Omni-Path Host Fabric Interface Adapter 100 Series 1 Port PCIe x16
+ 410.00 €
Ajout carte Mellanox ConnectX-4 Lx Dual Port 25Gb SFP28
+ 259.00 €
Ajout carte QLogic 41262 Dual Port 25GbE SFP28
+ 205.00 €
Ajout carte QLogic 41162 Dual Port 10GbE Base-T
+ 190.00 €
Ajout carte QLogic 41112 Dual Port 10GbE SFP+
+ 180.00 €
Ajout carte réseau Intel XXV710 deux ports 25 Gb SFP28
+ 284.00 €
Carte Mellanox ConnectX-5 Simple Port EDR VPI QSFP28
+ 704.00 €
ConnectX-4 VPI adapter card, EDR IB (100Gb/s), Double-port SFP28
+ 1247.00 €
ConnectX-6 HDR100, 100Gbits Single Port QSFP56
+ 704.00 €
Dispositifs optiques
0.00 €
Ajout Transceiver 10 Gb SR SFP+ pour les cartes 10 Gb Intel
+ 90.00 €
Dell Networking Câble Direct Attach Twinaxial SFP+ DELL 3 mètres
+ 25.00 €
Dell Networking Câble Direct Attach Twinaxial SFP28 (25G) DELL 3 mètres
+ 105.00 €
Dispositifs optiques Mellanox
0.00 €
Ajout Transceiver 10 Gb SR SFP+ pour les cartes 10 Gb Mellanox
+ 105.00 €
Options & dispositifs optiques divers
0.00 €
Ajout Transceiver 10 Gb SR SFP+ pour les cartes 10 Gb Broadcom et Qlogic
+ 90.00 €
Ajout Transceiver 25 Gb SR SFP+ pour les cartes 25 Gb Broadcom, Qlogic, Intel et Mellanox
+ 368.00 €
Carte d'administration à distance
iDRAC9, Express
0.00 €
iDRAC9, Express
0.00 €
Passage à carte iDRAC 9 Enterprise
+ 17.00 €
Carte d'administration à distance
Group Manager désactivé
0.00 €
Activation d'iDRAC9 Group Manager
0.00 €
Group Manager désactivé
0.00 €
Carte d'administration à distance (autre)
Mot de passe iDRAC9 Aléatoire
0.00 €
Mot de passe iDRAC9 Aléatoire
0.00 €
Mot de passe iDRAC9 Classique
0.00 €
Carte d'administration à distance (autre)
0.00 €
Passage à carte iDRAC 9 Enterprise avec carte SD Vflash 16 GB
+ 68.00 €
Alimentations (Passage)
1 bloc d'alimenation de 495 Watts Platinium avec câble d'alimentation 2 mètres
0.00 €
1 bloc d'alimenation de 495 Watts Platinium avec câble d'alimentation 2 mètres
0.00 €
Passage à double alimentation redondante 495W Platinium (1+1)
+ 75.00 €
Passage à mono alimentation non redondante 750W Platinium (1+0)
+ 19.00 €
Passage à double alimentation redondante 750W Platinium (1+1)
+ 117.00 €
Passage à mono alimentation non redondante 750W Titanium (1+0)
+ 47.00 €
Passage à double alimentation redondante 750W Titanium (1+1)
+ 191.00 €
Passage à mono alimentation non redondante 1100W Platinium ( 1+0)
+ 33.00 €
Passage à double alimentation redondante 1100W Platinium (1+1)
+ 150.00 €
Passage à mono alimentation non redondante 1600W Platinium ( 1+0)
+ 75.00 €
Passage à double alimentation redondante 1600W Platinium (1+1)
+ 180.00 €
Rails pour rack
Sans rails de rack ni bras de gestion des câbles
0.00 €
Rails coulissant Ready rails avec bras de management de cables, pour rack 4 montants
+ 75.00 €
Rails coulissant Ready rails sans bras de management de cables, pour rack 4 montants
+ 50.00 €
Kit de mise en rack statique pour racks 2 ou 4 montants
+ 50.00 €
Sans rails de rack ni bras de gestion des câbles
0.00 €
Cadre
Cadre standard Dell EMC sans bordure
0.00 €
Cadre standard Dell EMC sans bordure
0.00 €
Panneau avant métallique façade
+ 17.00 €
Panneau avant métallique façade et écran LCD
+ 50.00 €
Panneau Quick Sync
Sans Quick Sync
0.00 €
Sans Quick Sync
0.00 €
Module Quick Sync (Bluetooth/Wifi)
+ 80.00 €
Cordons d'alimentation
Cordons d'alimentation style PDU 2M (C13/C14 10A)
0.00 €
Passage de câble d'alimentation de 2m à 0,6m
0.00 €
Cordons d'alimentation style PDU 2M (C13/C14 10A)
0.00 €
Passage de câble d'alimentation de 2m à 4m
0.00 €
Extensions de garanties
+ProSupport 5 ans, intervention sur site J+1: support professionnel de +niveau 2 comprenant assistance matériel et logiciel, 24H/24, 7j/7
0.00 €
ProSupport + 5 ans, intervention sur site J+1: support professionnel de niveau 2 +comprenant assistance matériel et logiciel, 24H/24, 7j/7
0.00 €
Extension de garantie 5 ans intervention H+4 (24h/24h, 7j/7j) DELL Prosupport
+ 250.00 €
Extension de garantie 7 ans intervention J+1 (heures ouvrées, jours ouvrés) DELL Prosupport
+ 270.00 €
Extension de garantie 7 ans intervention H+4 (24h/24h, 7j/7j) DELL Prosupport
+ 650.00 €
Extension de garantie disque dur
0.00 €
Livraison supplementaire
Delivery Plus Flag
0.00 €
Regulatory
PowerEdge R640 CE,CCC,BIS Marking
0.00 €
PowerEdge R640 CE,CCC,BIS Marking
0.00 €
Cadre
None
0.00 €
Services de configuration - Rapport sur les ressources
+ProSupport 5 ans, intervention sur site J+1: support professionnel de +niveau 2 comprenant assistance matériel et logiciel, 24H/24, 7j/7
0.00 €
Prix1175.00 €
Options0.00 €
Total1175.00 €
+
+ + + + + +
Besoin d'aide ?
+ + + +
+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/readme.md b/readme.md index 75f7d29..209e25d 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,4 @@ # ConCho : Configuration Choser -a tool to help choosing the best quality price ratio for a compute node \ No newline at end of file +a tool to help choosing the best quality price ratio for a compute node + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1a73f93 --- /dev/null +++ b/setup.py @@ -0,0 +1,7 @@ +from setuptools import setup, find_packages + + +setup(name='concho', + version='1.0', + packages=find_packages(), + install_requires=['lxml', 'numpy', 'matplotlib']) \ No newline at end of file diff --git a/tests/test1.py b/tests/test1.py new file mode 100644 index 0000000..b1f7f5a --- /dev/null +++ b/tests/test1.py @@ -0,0 +1,10 @@ +from concho.dell import DellConfiguratorParser +from concho.procs_chooser import plot_system_efficiency + +def test_function(): + # configurator = DellMatinfoConfigurator('rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html') + # print(configurator) + plot_system_efficiency() + +if __name__ == '__main__': + test_function() \ No newline at end of file