added dell poweredge r6725 configurator

- added support for current amd epyc cpus

work related to [https://bugzilla.ipr.univ-rennes.fr/show_bug.cgi?id=4171]
This commit is contained in:
Guillaume Raffy 2025-10-22 16:03:53 +02:00
parent 4454023128
commit 8d92cf77f0
5 changed files with 11642 additions and 33 deletions

File diff suppressed because one or more lines are too long

View File

@ -181,6 +181,8 @@ class Cpu(Item):
return 'genoa' # zen 4 return 'genoa' # zen 4
elif re.match('amd-epyc-97[0-9f]4', proc_id): elif re.match('amd-epyc-97[0-9f]4', proc_id):
return 'bergamo' # zen 4c return 'bergamo' # zen 4c
elif re.match('amd-epyc-9[0-9][0-9]5', proc_id):
return 'turin' # zen 5 and zen 5c
else: else:
assert False, 'unhandled processor id : %s' % proc_id assert False, 'unhandled processor id : %s' % proc_id
@ -276,8 +278,17 @@ class Cpu(Item):
if proc_arch in ['genoa', 'bergamo']: # zen4 if proc_arch in ['genoa', 'bergamo']: # zen4
# [/home/graffy/work/concho/cpus_may2023_v3.pdf]] # [/home/graffy/work/concho/cpus_may2023_v3.pdf]]
# AMD has two AVX-2 256 bit units, which can do one coupled AVX-512 FMA instruction, which puts the FLOPS per cycle to 16 # AMD has two AVX-2 256 bit units, which can do one coupled AVX-512 FMA instruction, which puts the FLOPS per cycle to 16
# from https://www.amd.com/en/blogs/2025/leadership-hpc-performance-with-5th-generation-amd.html:
# 2. AMD EPYC 9004 CPUs(“Zen4”) already had AVX-512 instructions; however, those CPUs are using 2 clock cycles to achieve AVX-512 calculation due to FMA* and dual AVX256 data path. So, 256b datapath / 64b (datatype) * (2 pipes * 2 ops/lane) =16 floating-point operations per clock cycle.
dp_flops_per_cycle_per_core = 16 dp_flops_per_cycle_per_core = 16
if proc_arch in ['turin']: # zen5
# from https://www.amd.com/en/blogs/2025/leadership-hpc-performance-with-5th-generation-amd.html:
# 3. AMD EPYC 9005 CPUs(“Zen5”) have a full 512b data path due to FMA* and dual native AVX512 per core. So, 512b datapath / 64b (datatype) * (2 pipes * 2 ops/lane) =32 floating-point operations per clock cycle.
# *FMA stands for fused multiply-add and it is a floating-point multiply-add operation performed in one step (fused operation), with a single rounding. Specifically, it calculates FMA(a,b,c)=(a×b)+c with a single rounding step.
dp_flops_per_cycle_per_core = 32
# print(self.uid, dp_flops_per_cycle) # print(self.uid, dp_flops_per_cycle)
assert dp_flops_per_cycle_per_core > 0, f'failed to get the number of dp floating operations per cycle per core of {proc_arch}' assert dp_flops_per_cycle_per_core > 0, f'failed to get the number of dp floating operations per cycle per core of {proc_arch}'
return dp_flops_per_cycle_per_core return dp_flops_per_cycle_per_core
@ -295,7 +306,8 @@ class Cpu(Item):
'milan': 8, 'milan': 8,
'siena': 6, 'siena': 6,
'genoa': 12, 'genoa': 12,
'bergamo': 12 'bergamo': 12,
'turin': 12
}[self.architecture] }[self.architecture]
@ -348,6 +360,13 @@ def get_simd_id(proc_arch: CpuArchitecture) -> SimdId:
'siena': 'avx2', 'siena': 'avx2',
'genoa': 'avx2', 'genoa': 'avx2',
'bergamo': 'avx2', 'bergamo': 'avx2',
'turin': 'avx-512',
# from https://www.amd.com/en/blogs/2025/leadership-hpc-performance-with-5th-generation-amd.html:
# 2. AMD EPYC 9004 CPUs(“Zen4”) already had AVX-512 instructions; however, those CPUs are using 2 clock cycles to achieve AVX-512 calculation due to FMA* and dual AVX256 data path. So, 256b datapath / 64b (datatype) * (2 pipes * 2 ops/lane) =16 floating-point operations per clock cycle.
# 3. AMD EPYC 9005 CPUs(“Zen5”) have a full 512b data path due to FMA* and dual native AVX512 per core. So, 512b datapath / 64b (datatype) * (2 pipes * 2 ops/lane) =32 floating-point operations per clock cycle.
# *FMA stands for fused multiply-add and it is a floating-point multiply-add operation performed in one step (fused operation), with a single rounding. Specifically, it calculates FMA(a,b,c)=(a×b)+c with a single rounding step.
#
}[proc_arch] }[proc_arch]

View File

@ -491,6 +491,14 @@ class DellConfiguratorParser(IHtmlConfiguratorParser):
cpu_id = "intel-xeon-%s-%s" % (cpu_class, match['cpu_number'].lower()) cpu_id = "intel-xeon-%s-%s" % (cpu_class, match['cpu_number'].lower())
if self.additional_cpu_is_automatic(): if self.additional_cpu_is_automatic():
num_cpus = 2 num_cpus = 2
if match is None:
# examples from dell 20/10/2025:
# Processeur AMD EPYC 9135 3,65 GHz, 16C/32T, 64 Mo de cache (200 W), mémoire DDR5 à 6400 MT/s
match = re.match(r'^(Processeur\s)?AMD[®]?\sEPYC[®]?\s+(?P<cpu_number>[0-9][0-9][0-9][0-9][F]?)\s.*', label)
if match:
cpu_id = "amd-epyc-%s" % (match['cpu_number'].lower())
if self.additional_cpu_is_automatic():
num_cpus = 2
assert match, 'unhandled label : %s' % label assert match, 'unhandled label : %s' % label
# print(match['cpu_class'], match['cpu_number']) # print(match['cpu_class'], match['cpu_number'])
option = Option(Cpu(cpu_id), price / num_cpus) option = Option(Cpu(cpu_id), price / num_cpus)
@ -685,34 +693,51 @@ class DellConfiguratorParser(IHtmlConfiguratorParser):
@staticmethod @staticmethod
def _estimate_base_cpu_price_from_public_prices(cpu_uid: CpuId) -> Price: def _estimate_base_cpu_price_from_public_prices(cpu_uid: CpuId) -> Price:
# estimation of xeon 6505p price on matinfo 6: public_prices_usd = {}
matinfo6_upgrade_prices_eur = {}
# matinfo 6 prices: if cpu_uid == 'intel-xeon-performance-6505p':
# - upgrade from 2 x 6505p to 2 x 6507p: 186.0 € # retail prices [https://en.wikipedia.org/wiki/Granite_Rapids#Granite_Rapids-SP]:
# - upgrade from 2 x 6505p to 2 x 6515p: 242.0 € public_prices_usd = {
# - upgrade from 2 x 6505p to 2 x 6737p: 6465.0 € 'intel-xeon-performance-6505p': 563.0,
# retail prices [https://en.wikipedia.org/wiki/Granite_Rapids#Granite_Rapids-SP]: 'intel-xeon-performance-6507p': 765.0,
public_prices_usd = { 'intel-xeon-performance-6515p': 740.0,
'intel-xeon-performance-6505p': 563.0, 'intel-xeon-performance-6517p': 1195.0,
'intel-xeon-performance-6507p': 765.0, # 'intel-xeon-performance-6730p': 2234.0,
'intel-xeon-performance-6515p': 740.0, # 'intel-xeon-performance-6737p': 4995.0,
'intel-xeon-performance-6517p': 1195.0, # 'intel-xeon-performance-6740p': 4650.0,
# 'intel-xeon-performance-6730p': 2234.0, # 'intel-xeon-performance-6767p': 9595.0,
# 'intel-xeon-performance-6737p': 4995.0, # 'intel-xeon-performance-6787p': 10400.0,
# 'intel-xeon-performance-6740p': 4650.0, }
# 'intel-xeon-performance-6767p': 9595.0, # matinfo 6 upgrade (from 2 x intel-xeon-performance-6505p) prices:
# 'intel-xeon-performance-6787p': 10400.0, # - upgrade from 2 x 6505p to 2 x 6507p: 186.0 €
} # - upgrade from 2 x 6505p to 2 x 6515p: 242.0 €
matinfo6_upgrade_prices_eur = { # - upgrade from 2 x 6505p to 2 x 6737p: 6465.0 €
'intel-xeon-performance-6507p': 186.0, matinfo6_upgrade_prices_eur = {
'intel-xeon-performance-6515p': 242.0, 'intel-xeon-performance-6507p': 186.0,
'intel-xeon-performance-6517p': 902.0, 'intel-xeon-performance-6515p': 242.0,
# 'intel-xeon-performance-6730p': 3674.0, 'intel-xeon-performance-6517p': 902.0,
# 'intel-xeon-performance-6737p': 6465.0, # 'intel-xeon-performance-6730p': 3674.0,
# 'intel-xeon-performance-6740p': 6724.0, # 'intel-xeon-performance-6737p': 6465.0,
# 'intel-xeon-performance-6767p': 9672.0, # 'intel-xeon-performance-6740p': 6724.0,
# 'intel-xeon-performance-6787p': 10775.0, # 'intel-xeon-performance-6767p': 9672.0,
} # 'intel-xeon-performance-6787p': 10775.0,
}
elif cpu_uid == 'amd-epyc-9115':
# retail prices [https://en.wikipedia.org/wiki/Epyc] on 22/10/2025:
public_prices_usd = {
'amd-epyc-9115': 726.0,
'amd-epyc-9135': 1214.0,
'amd-epyc-9255': 2495.0,
'amd-epyc-9275f': 3439.0,
}
# matinfo 6 upgrade (from 2 x amd-epyc-9115) prices:
matinfo6_upgrade_prices_eur = {
'amd-epyc-9135': 707.0,
'amd-epyc-9255': 2556.0,
'amd-epyc-9275f': 3943.0,
}
else:
assert False, 'estimation of base cpu price from public prices not implemented for %s' % cpu_uid
# let p_x be the public price of cpu x in usd (known) # let p_x be the public price of cpu x in usd (known)
# let m_x be the matinfo6 price of cpu x in eur (unknown) # let m_x be the matinfo6 price of cpu x in eur (unknown)
# we assume m_x = p_x * r, where the unknown r encompasses currency conversion usd->eur and reseller discount # we assume m_x = p_x * r, where the unknown r encompasses currency conversion usd->eur and reseller discount
@ -798,6 +823,7 @@ class DellConfiguratorParser(IHtmlConfiguratorParser):
base_cpu_price = { base_cpu_price = {
'amd-epyc-7262': 550.0, 'amd-epyc-7262': 550.0,
'amd-epyc-9115': DellConfiguratorParser._estimate_base_cpu_price_from_public_prices(cpu_uid=base_cpu.uid),
'intel-xeon-performance-6505p': DellConfiguratorParser._estimate_base_cpu_price_from_public_prices(cpu_uid=base_cpu.uid), 'intel-xeon-performance-6505p': DellConfiguratorParser._estimate_base_cpu_price_from_public_prices(cpu_uid=base_cpu.uid),
}[base_cpu.uid] }[base_cpu.uid]
configurator.modules['processor'].add_option(Option(base_cpu, base_cpu_price)) configurator.modules['processor'].add_option(Option(base_cpu, base_cpu_price))
@ -1009,7 +1035,7 @@ class DellConfiguratorParser2025(DellConfiguratorParser):
title_span_element = conf_title_element.xpath(".//span")[0] title_span_element = conf_title_element.xpath(".//span")[0]
assert title_span_element is not None assert title_span_element is not None
title = title_span_element.text_content().replace('\n', '').strip() # eg 'Cat2 Conf 2-2-07: Dell Poweredge R670' title = title_span_element.text_content().replace('\n', '').strip() # eg 'Cat2 Conf 2-2-07: Dell Poweredge R670'
match = re.match(r'^Cat[0-9]+ Conf [0-9\-]+: Dell Poweredge (?P<chassis_type>[CR][0-9][0-9][0-9][0-9]?).*', title) match = re.match(r'^Cat[0-9]+ Conf\s+[0-9\-]+: Dell Poweredge (?P<chassis_type>[CR][0-9][0-9][0-9][0-9]?).*', title)
assert match, 'unhandled title : %s' % title assert match, 'unhandled title : %s' % title
# print(match['cpu_class'], match['cpu_number']) # print(match['cpu_class'], match['cpu_number'])
chassis_id = "dell-poweredge-%s" % (match['chassis_type'].lower(), ) # eg "dell-poweredge-r670" chassis_id = "dell-poweredge-%s" % (match['chassis_type'].lower(), ) # eg "dell-poweredge-r670"
@ -1202,7 +1228,7 @@ class DellConfiguratorParser2025(DellConfiguratorParser):
def _parse_base_config(self, html_root: HtmlElement, configurator: Configurator) -> Config: def _parse_base_config(self, html_root: HtmlElement, configurator: Configurator) -> Config:
base_config = Config(configurator) base_config = Config(configurator)
base_config.num_servers = configurator.chassis.item.max_num_servers base_config.num_servers = configurator.chassis.item.max_num_servers
if self.additional_cpu_is_automatic(self): if self.additional_cpu_is_automatic():
base_config.num_cpu_per_server = 2 base_config.num_cpu_per_server = 2
else: else:
base_config.num_cpu_per_server = 1 base_config.num_cpu_per_server = 1
@ -1212,9 +1238,13 @@ class DellConfiguratorParser2025(DellConfiguratorParser):
# Processeur Intel Xeon Silver 4208 2.1GHz,11M Cache,9.60GT/s, 2UPI,No Turbo, HT,8C/16T (85W) - DDR4-2400 # 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[®]? 6 (?P<cpu_class>Silver|Gold|Platinium|Performance) (?P<cpu_number>[0-9][0-9][0-9][0-9][PRLYU]?).*', item_label) # match = re.match(r'^Processeur Intel[®]? Xeon[®]? 6 (?P<cpu_class>Silver|Gold|Platinium|Performance) (?P<cpu_number>[0-9][0-9][0-9][0-9][PRLYU]?).*', item_label)
match = re.match(r'^Processeur Intel[®]? Xeon[®]?\s+6\s+(?P<cpu_class>Silver|Gold|Platinium|Performance)\s+(?P<cpu_number>[0-9][0-9][0-9][0-9][PRLYU]?).*', item_label) match = re.match(r'^Processeur Intel[®]? Xeon[®]?\s+6\s+(?P<cpu_class>Silver|Gold|Platinium|Performance)\s+(?P<cpu_number>[0-9][0-9][0-9][0-9][PRLYU]?).*', item_label)
assert match, 'unhandled label : %s' % item_label
if match: if match:
cpu_id = "intel-xeon-%s-%s" % (match['cpu_class'].lower(), match['cpu_number'].lower()) cpu_id = "intel-xeon-%s-%s" % (match['cpu_class'].lower(), match['cpu_number'].lower())
if not match:
# Processeur AMD EPYC 9115 2,60 GHz, 16C/32T, 64 Mo de cache (125 W), mémoire DDR5 à 6400 MT/s
match = re.match(r'^Processeur AMD EPYC\s+(?P<cpu_number>[0-9][0-9][0-9][0-9]).*', item_label)
cpu_id = "amd-epyc-%s" % (match['cpu_number'].lower(), )
assert match, 'unhandled label : %s' % item_label assert match, 'unhandled label : %s' % item_label
# print(match['cpu_class'], match['cpu_number']) # print(match['cpu_class'], match['cpu_number'])

View File

@ -152,6 +152,7 @@ def plot_configs(configs: List[Config], xaxis_def: ConfigAxisDef, yaxis_def: Con
'siena': 1.0, 'siena': 1.0,
'genoa': 1.0, 'genoa': 1.0,
'bergamo': 1.0, 'bergamo': 1.0,
'turin': 1.0,
}[Cpu(proc_id).architecture] }[Cpu(proc_id).architecture]
# if model == 'r620': # if model == 'r620':
# color = 'r' # color = 'r'
@ -168,8 +169,9 @@ def plot_configs(configs: List[Config], xaxis_def: ConfigAxisDef, yaxis_def: Con
'dell-poweredge-r620': 0.6, 'dell-poweredge-r620': 0.6,
'dell-poweredge-r630': 0.6, 'dell-poweredge-r630': 0.6,
'dell-poweredge-r640': 0.6, 'dell-poweredge-r640': 0.6,
'dell-poweredge-r670': 0.6,
'dell-poweredge-r6525': 0.5, 'dell-poweredge-r6525': 0.5,
'dell-poweredge-r670': 0.6,
'dell-poweredge-r6725': 0.0,
'dell-poweredge-c4310': 0.6, 'dell-poweredge-c4310': 0.6,
'dell-poweredge-r730': 0.4, 'dell-poweredge-r730': 0.4,
'dell-poweredge-r7525': 0.3, 'dell-poweredge-r7525': 0.3,

View File

@ -20,6 +20,7 @@ class Test(unittest.TestCase):
logging.info('Starting test_dell2_configs') logging.info('Starting test_dell2_configs')
configurators = [ configurators = [
HtmlConfigurator(Path('catalogs/dell/2025-10/20251020 - Cat2 Conf 2-2-07_ Dell Poweredge R670.html'), DellConfiguratorParser2025()), HtmlConfigurator(Path('catalogs/dell/2025-10/20251020 - Cat2 Conf 2-2-07_ Dell Poweredge R670.html'), DellConfiguratorParser2025()),
HtmlConfigurator(Path('catalogs/dell/2025-10/20251022 - Cat2 Conf 2-2-09_ Dell Poweredge R6725.html'), DellConfiguratorParser2025()),
] ]
def config_filter(config: Config) -> bool: def config_filter(config: Config) -> bool: