improved dimm filling in cpu slots
previously, only one dimm was used per channel, which resulted in too expensive configurations when the number of cores increased.
This commit is contained in:
parent
53eb1be087
commit
a22f88ec6a
101
concho/config.py
101
concho/config.py
|
@ -2,6 +2,7 @@ import re
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
import numpy
|
import numpy
|
||||||
from concho import dell
|
from concho import dell
|
||||||
|
import math
|
||||||
|
|
||||||
class Item():
|
class Item():
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ class Config():
|
||||||
def __init__(self, configurator):
|
def __init__(self, configurator):
|
||||||
self.configurator = configurator
|
self.configurator = configurator
|
||||||
self.num_servers = 0
|
self.num_servers = 0
|
||||||
self.num_cpu_per_server = 0
|
self._num_cpu_per_server = 0
|
||||||
self.cpu = None
|
self.cpu = None
|
||||||
self.cpu_slots_mem = []
|
self.cpu_slots_mem = []
|
||||||
|
|
||||||
|
@ -199,6 +200,48 @@ class Config():
|
||||||
def chassis(self):
|
def chassis(self):
|
||||||
return self.configurator.chassis.item
|
return self.configurator.chassis.item
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _find_dimm_combination(num_dimm_slots_per_channel, min_ram_per_channel, available_dimms):
|
||||||
|
available_dimms.append(Option(Dimm(0,0,'dummy'), 0.0)) # fake dimm to represent empty slot
|
||||||
|
slot_options = []
|
||||||
|
|
||||||
|
# try all combinations of dimms
|
||||||
|
best_slot_options = None
|
||||||
|
best_price = None
|
||||||
|
for slot_index in range(num_dimm_slots_per_channel):
|
||||||
|
slot_options.append(0)
|
||||||
|
no_more_configs = False
|
||||||
|
while no_more_configs == False:
|
||||||
|
config_capacity = 0
|
||||||
|
config_price = 0
|
||||||
|
for slot_index in range(num_dimm_slots_per_channel):
|
||||||
|
dimm_option = available_dimms[slot_options[slot_index]]
|
||||||
|
config_capacity += float(dimm_option.item.num_gb) * math.pow(2.0, 30.0)
|
||||||
|
config_price += dimm_option.price
|
||||||
|
if config_capacity >= min_ram_per_channel: # only remember the combination if it complies with the minimal memory constraint
|
||||||
|
if best_price is None or config_price < best_price:
|
||||||
|
best_price = config_price
|
||||||
|
best_slot_options = slot_options.copy()
|
||||||
|
# generate the next combination of dimms
|
||||||
|
for slot_index in range(num_dimm_slots_per_channel):
|
||||||
|
slot_options[slot_index] += 1
|
||||||
|
if slot_options[slot_index] < len(available_dimms):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if slot_index == num_dimm_slots_per_channel - 1:
|
||||||
|
no_more_configs = True # all combinations of dimm in the slots have been covered
|
||||||
|
else:
|
||||||
|
slot_options[slot_index] = 0
|
||||||
|
|
||||||
|
assert best_slot_options is not None, "Failed to find a dimm combination that provides %f bytes per channel." % min_ram_per_channel
|
||||||
|
slot_dimms = []
|
||||||
|
for dimm_slot_index in range(num_dimm_slots_per_channel):
|
||||||
|
dimm = available_dimms[best_slot_options[dimm_slot_index]].item
|
||||||
|
if dimm.num_gb == 0:
|
||||||
|
dimm = None
|
||||||
|
slot_dimms.append(dimm)
|
||||||
|
return slot_dimms
|
||||||
|
|
||||||
def set_ram(self, ram_per_core=None, ram_per_server=None, ram_per_cpu=None):
|
def set_ram(self, ram_per_core=None, ram_per_server=None, ram_per_cpu=None):
|
||||||
|
|
||||||
# ramUpgradePrice128Gb = {
|
# ramUpgradePrice128Gb = {
|
||||||
|
@ -225,33 +268,14 @@ class Config():
|
||||||
ram_per_cpu = ram_per_server / self.num_cpu_per_server
|
ram_per_cpu = ram_per_server / self.num_cpu_per_server
|
||||||
|
|
||||||
ram_per_channel = ram_per_cpu / cpu.num_ram_channels
|
ram_per_channel = ram_per_cpu / cpu.num_ram_channels
|
||||||
dimm_capacity = None
|
|
||||||
if ram_per_channel > 64.0e9:
|
slot_dimms = Config._find_dimm_combination(self.configurator.chassis.item.num_dimm_slots_per_channel, ram_per_channel, self.configurator.get_dimm_options())
|
||||||
assert False, 'ram_per_channel is too big (%f bytes > 64 Gb)' % ram_per_channel
|
|
||||||
elif ram_per_channel > 32.0e9:
|
print(cpu.uid, cpu.num_cores, ram_per_channel, [0 if dimm is None else dimm.num_gb for dimm in slot_dimms])
|
||||||
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
|
|
||||||
print(cpu.uid, cpu.num_cores, ram_per_channel)
|
|
||||||
for cpu_slot_mem in self.cpu_slots_mem:
|
for cpu_slot_mem in self.cpu_slots_mem:
|
||||||
for mem_channel in cpu_slot_mem.mem_channels:
|
for mem_channel in cpu_slot_mem.mem_channels:
|
||||||
for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel):
|
for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel):
|
||||||
mem_channel.dimms[dimm_slot_index] = dimm
|
mem_channel.dimms[dimm_slot_index] = slot_dimms[dimm_slot_index]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ram_size(self):
|
def ram_size(self):
|
||||||
|
@ -293,20 +317,38 @@ class Config():
|
||||||
return flops
|
return flops
|
||||||
|
|
||||||
|
|
||||||
def set_cpu(self, cpu):
|
def _init_dimm_slots(self):
|
||||||
self.cpu = cpu
|
|
||||||
# create the dimm slots
|
# create the dimm slots
|
||||||
self.cpu_slots_mem = []
|
self.cpu_slots_mem = []
|
||||||
|
|
||||||
|
if self.cpu is None:
|
||||||
|
return
|
||||||
|
|
||||||
for cpu_index in range(self.num_cpu_per_server):
|
for cpu_index in range(self.num_cpu_per_server):
|
||||||
cpu_slot_mem = CpuSlotMem()
|
cpu_slot_mem = CpuSlotMem()
|
||||||
|
|
||||||
for channel_index in range(cpu.num_ram_channels):
|
for channel_index in range(self.cpu.num_ram_channels):
|
||||||
mem_channel = MemChannel()
|
mem_channel = MemChannel()
|
||||||
for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel):
|
for dimm_slot_index in range(self.configurator.chassis.item.num_dimm_slots_per_channel):
|
||||||
mem_channel.dimms.append(None) # dimm slots are empty
|
mem_channel.dimms.append(None) # dimm slots are empty
|
||||||
cpu_slot_mem.mem_channels.append(mem_channel)
|
cpu_slot_mem.mem_channels.append(mem_channel)
|
||||||
self.cpu_slots_mem.append(cpu_slot_mem)
|
self.cpu_slots_mem.append(cpu_slot_mem)
|
||||||
|
|
||||||
|
def set_cpu(self, cpu):
|
||||||
|
self.cpu = cpu
|
||||||
|
# update the dimm slots accordingly
|
||||||
|
self._init_dimm_slots()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def num_cpu_per_server(self):
|
||||||
|
return self._num_cpu_per_server
|
||||||
|
|
||||||
|
@num_cpu_per_server.setter
|
||||||
|
def num_cpu_per_server(self, num_cpu_per_server):
|
||||||
|
self._num_cpu_per_server = num_cpu_per_server
|
||||||
|
# update the dimm slots accordingly
|
||||||
|
self._init_dimm_slots()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def num_cpus(self):
|
def num_cpus(self):
|
||||||
return self.num_cpu_per_server * self.num_servers
|
return self.num_cpu_per_server * self.num_servers
|
||||||
|
@ -353,6 +395,9 @@ class Configurator():
|
||||||
return dimm
|
return dimm
|
||||||
assert False, 'failed to find an option for a dimm of capacity %d gb' % dimm_capacity
|
assert False, 'failed to find an option for a dimm of capacity %d gb' % dimm_capacity
|
||||||
|
|
||||||
|
def get_dimm_options(self):
|
||||||
|
return list(self.modules['ram'].options.values())
|
||||||
|
|
||||||
def get_item(self, item_uid):
|
def get_item(self, item_uid):
|
||||||
for module in self.modules.values():
|
for module in self.modules.values():
|
||||||
if item_uid in module.options:
|
if item_uid in module.options:
|
||||||
|
|
|
@ -142,9 +142,9 @@ def plot_system_efficiency():
|
||||||
if not cpu.architecture in ['coffeelake', 'skylake','cascadelake']:
|
if not cpu.architecture in ['coffeelake', 'skylake','cascadelake']:
|
||||||
continue
|
continue
|
||||||
config = configurator.create_config()
|
config = configurator.create_config()
|
||||||
|
config.num_cpu_per_server = config.configurator.chassis.item.num_cpu_slots_per_server
|
||||||
config.set_cpu(cpu)
|
config.set_cpu(cpu)
|
||||||
config.set_ram(ram_per_core=4.0e9)
|
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' )
|
item_label = numpy.append( item_label, config.chassis.uid + '_' + cpu.uid + '_' + str(config.ram_size) + 'gb' )
|
||||||
# print('procOptionPrice', procOptionPrice)
|
# print('procOptionPrice', procOptionPrice)
|
||||||
# config_price = procOptionPrice
|
# config_price = procOptionPrice
|
||||||
|
|
Loading…
Reference in New Issue