now concho computes the price of the memory as well
- the empty machine price is now correct (the base memory is substracted) - also displays the mem size on the graph now that all machines don't have the same amount of memory nb : work involved for Bug 2886 - Devis pour l'achat d'un nouveau noeud pour le cluster (crédits TS 2020)
This commit is contained in:
		
							parent
							
								
									93a8b77231
								
							
						
					
					
						commit
						053d0f17ac
					
				|  | @ -17,6 +17,7 @@ class Chassis(Item): | |||
|         self.num_cpu_slots_per_server = 2 | ||||
|         if re.match('dell-poweredge-r9.*', uid): | ||||
|             self.num_cpu_slots_per_server = 4 | ||||
|         self.num_dimm_slots_per_channel = 2 | ||||
| 
 | ||||
| class Dimm(Item): | ||||
| 
 | ||||
|  | @ -34,7 +35,7 @@ class Cpu(Item): | |||
|         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) | ||||
|             # print(cpu_id) | ||||
|             if cpu_id == proc_id: | ||||
|                 # print('found '+procId) | ||||
|                 break | ||||
|  | @ -174,6 +175,15 @@ def get_simd_id(proc_arch): | |||
|         'coffeelake':'avx2' | ||||
|         }[proc_arch] | ||||
| 
 | ||||
| class MemChannel(): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.dimms = [] | ||||
| 
 | ||||
| class CpuSlotMem(): | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         self.mem_channels = [] | ||||
| 
 | ||||
| class Config(): | ||||
| 
 | ||||
|  | @ -182,7 +192,8 @@ class Config(): | |||
|         self.num_servers = 0 | ||||
|         self.num_cpu_per_server = 0 | ||||
|         self.cpu = None | ||||
|         self.dimms_per_channel = [] | ||||
|         self.cpu_slots_mem = [] | ||||
| 
 | ||||
| 
 | ||||
|     @property | ||||
|     def chassis(self): | ||||
|  | @ -236,16 +247,39 @@ class Config(): | |||
|         # dimm_capacity = 16 | ||||
|         dimm = self.configurator.get_dimm(dimm_capacity) | ||||
|         assert dimm | ||||
|         self.dimms_per_channel = [ dimm ] | ||||
|         print(cpu.uid, cpu.num_cores, ram_per_channel) | ||||
|         for cpu_slot_mem in self.cpu_slots_mem: | ||||
|             for mem_channel in cpu_slot_mem.mem_channels: | ||||
|                 for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel): | ||||
|                     mem_channel.dimms[dimm_slot_index] = dimm | ||||
| 
 | ||||
|     @property | ||||
|     def ram_size(self): | ||||
|         ram_size = 0 | ||||
|         for cpu_slot_mem in self.cpu_slots_mem: | ||||
|             for mem_channel in cpu_slot_mem.mem_channels: | ||||
|                 for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel): | ||||
|                     dimm = mem_channel.dimms[dimm_slot_index] | ||||
|                     if dimm is not None: | ||||
|                         dimm = self.configurator.get_item(dimm.uid) | ||||
|                         ram_size += self.num_servers * dimm.num_gb | ||||
|         return ram_size | ||||
| 
 | ||||
|     @property | ||||
|     def ram_price(self): | ||||
|         ram_price = 0.0 | ||||
|         for cpu_slot_mem in self.cpu_slots_mem: | ||||
|             for mem_channel in cpu_slot_mem.mem_channels: | ||||
|                 for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel): | ||||
|                     dimm = mem_channel.dimms[dimm_slot_index] | ||||
|                     if dimm is not None: | ||||
|                         dimm_price = self.configurator.get_item_price(dimm.uid) | ||||
|                         ram_price += self.num_servers * dimm_price | ||||
|         return ram_price | ||||
| 
 | ||||
|      | ||||
|     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)) | ||||
|         price += self.num_servers * self.num_cpu_per_server * self.configurator.get_item_price(self.cpu.uid) + self.ram_price | ||||
|         assert price > 0.0 | ||||
|         return price | ||||
| 
 | ||||
|  | @ -261,7 +295,21 @@ class Config(): | |||
| 
 | ||||
|     def set_cpu(self, cpu): | ||||
|         self.cpu = cpu | ||||
|         # create the dimm slots | ||||
|         self.cpu_slots_mem = [] | ||||
|         for cpu_index in range(self.num_cpu_per_server): | ||||
|             cpu_slot_mem = CpuSlotMem() | ||||
|              | ||||
|             for channel_index in range(cpu.num_ram_channels): | ||||
|                 mem_channel = MemChannel() | ||||
|                 for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel): | ||||
|                     mem_channel.dimms.append(None)  # dimm slots are empty | ||||
|                 cpu_slot_mem.mem_channels.append(mem_channel) | ||||
|             self.cpu_slots_mem.append(cpu_slot_mem) | ||||
| 
 | ||||
|     @property | ||||
|     def num_cpus(self): | ||||
|         return self.num_cpu_per_server * self.num_servers | ||||
| 
 | ||||
| class Option(): | ||||
| 
 | ||||
|  | @ -305,6 +353,11 @@ class Configurator(): | |||
|                 return dimm | ||||
|         assert False, 'failed to find an option for a dimm of capacity %d gb' % dimm_capacity | ||||
| 
 | ||||
|     def get_item(self, item_uid): | ||||
|         for module in self.modules.values(): | ||||
|             if item_uid in module.options: | ||||
|                 return module.options[item_uid].item | ||||
| 
 | ||||
|     def get_item_price(self, item_uid): | ||||
|         for module in self.modules.values(): | ||||
|             if item_uid in module.options: | ||||
|  |  | |||
|  | @ -487,11 +487,9 @@ class DellConfiguratorParser(): | |||
|                         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)') | ||||
|     @classmethod | ||||
|     def _get_module_default_item(cls, module_label, html_root): | ||||
|         module_root_element = DellConfiguratorParser._get_module(html_root, module_label) | ||||
|         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 ']") | ||||
|  | @ -499,15 +497,37 @@ class DellConfiguratorParser(): | |||
|             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 (?P<cpu_class>Silver|Gold|Platinium) (?P<cpu_number>[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 | ||||
|                 assert price == 0.0, 'default items are expected to have a price of 0.0 € (%s s price is %f)' % (label, price) | ||||
|                 return label | ||||
|         assert False, 'failed to find the default item of module %s' % module_label | ||||
| 
 | ||||
|     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 | ||||
| 
 | ||||
|         # initialize cpu | ||||
|         item_label = DellConfiguratorParser._get_module_default_item('Processeurs (Passage)', html_root) | ||||
|         # 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 (?P<cpu_class>Silver|Gold|Platinium) (?P<cpu_number>[0-9][0-9][0-9][0-9][RLYU]?).*', item_label) | ||||
|         assert match, 'unhandled label : %s' % item_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)) | ||||
| 
 | ||||
|         # initialize the default ram dimms | ||||
|         item_label = DellConfiguratorParser._get_module_default_item('Mémoires (Passage)', html_root) | ||||
|         # Mémoire 16 Go DDR4 à 2933MHz (1x16Go) | ||||
|         match = re.match(r'^Mémoire (?P<num_gb>[0-9]+) Go DDR4 à (?P<num_mhz>[0-9]+)MHz \((?P<num_dimms>[0-9]+)x(?P<num_gb2>[0-9]+)Go\)', item_label) | ||||
|         assert match, 'unhandled label : %s' % item_label | ||||
|         assert int(match['num_dimms']) == 1 | ||||
|         assert match['num_gb'] == match['num_gb2'] | ||||
|         # print(match['cpu_class'], match['cpu_number']) | ||||
|         cpu_slot_index = 0 | ||||
|         mem_channel_index = 0 | ||||
|         dimm_slot = 0 | ||||
|         base_config.cpu_slots_mem[cpu_slot_index].mem_channels[mem_channel_index].dimms[dimm_slot] = Dimm(num_gb=int(match['num_gb']), num_mhz=int(match['num_mhz']), mem_type='rdimm') | ||||
| 
 | ||||
|         return base_config | ||||
| 
 | ||||
| 
 | ||||
|  | @ -570,7 +590,8 @@ class DellConfiguratorParser(): | |||
|                 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) | ||||
| 
 | ||||
|         configurator.chassis.price = base_price - configurator.base_config.num_cpus * configurator.get_item_price(configurator.base_config.cpu.uid) - configurator.base_config.ram_price | ||||
| 
 | ||||
| class DellMatinfoConfigurator(Configurator): | ||||
| 
 | ||||
|  | @ -583,5 +604,12 @@ class DellMatinfoConfigurator(Configurator): | |||
| 
 | ||||
| 
 | ||||
|     def create_config(self): | ||||
|         return copy.copy(self.base_config) | ||||
|         # config = copy.deepcopy(self.base_config) | ||||
|         config = Config(self) | ||||
|         config.num_servers = self.base_config.num_servers | ||||
|         config.num_cpu_per_server = self.base_config.num_cpu_per_server | ||||
|         config.set_cpu(self.base_config.cpu) | ||||
|         config.cpu_slots_mem = copy.deepcopy(self.base_config.cpu_slots_mem) | ||||
| 
 | ||||
|         return config | ||||
| 
 | ||||
|  |  | |||
|  | @ -76,7 +76,7 @@ def plot_system_efficiency(): | |||
| 
 | ||||
|     def getColorCodeFromItemLabel(label): | ||||
|         generation=label[-1] | ||||
|         (model, proc_id) = re.split('_', label) | ||||
|         (model, proc_id, ram_size) = re.split('_', label) | ||||
|         saturation = { | ||||
|             'sandy bridge':0.0, | ||||
|             'ivy bridge':0.2, | ||||
|  | @ -113,7 +113,7 @@ def plot_system_efficiency(): | |||
|         return matplotlib.colors.hsv_to_rgb((hue, saturation, value)) | ||||
| 
 | ||||
|     def get_marker_from_label(label): | ||||
|         (model, proc_id) = re.split('_', label) | ||||
|         (model, proc_id, ram_size) = re.split('_', label) | ||||
|         return get_marker(proc_id) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -125,14 +125,14 @@ def plot_system_efficiency(): | |||
|         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 = configurator.create_config() | ||||
|             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 | ||||
|             item_label = numpy.append( item_label, config.chassis.uid + '_' + cpu.uid + '_' + str(config.ram_size) + 'gb' ) | ||||
|             # print('procOptionPrice', procOptionPrice) | ||||
|             # config_price = procOptionPrice | ||||
|             # config_price += config.get_empty_price() | ||||
|  | @ -146,6 +146,7 @@ def plot_system_efficiency(): | |||
|             # 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)) | ||||
|             # print(item_label, config.get_price(), config.get_power_consumption()) | ||||
|             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]) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue