build: add optional NUMA and CPU counts detection

Add an option to automatically discover the host's NUMA and CPU counts
and use those values for a non cross-build.
Give users the option to override the per-arch default values or values
from cross files by specifying them on the command line with -Dmax_lcores
and -Dmax_numa_nodes.

Signed-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech>
Reviewed-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>
Reviewed-by: David Christensen <drc@linux.vnet.ibm.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
This commit is contained in:
Juraj Linkeš 2021-08-17 12:45:56 +02:00 committed by Thomas Monjalon
parent 9c8c806487
commit 8ef09fdc50
7 changed files with 86 additions and 6 deletions

View File

@ -102,6 +102,8 @@ F: meson_options.txt
F: config/
F: buildtools/chkincs/
F: buildtools/call-sphinx-build.py
F: buildtools/get-cpu-count.py
F: buildtools/get-numa-count.py
F: buildtools/list-dir-globs.py
F: buildtools/pkg-config/
F: buildtools/symlink-drivers-solibs.sh

View File

@ -0,0 +1,7 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2021 PANTHEON.tech s.r.o.
import os
print(os.cpu_count())

View File

@ -0,0 +1,24 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2021 PANTHEON.tech s.r.o.
import ctypes
import glob
import os
import subprocess
if os.name == 'posix':
if os.path.isdir('/sys/devices/system/node'):
numa_nodes = glob.glob('/sys/devices/system/node/node*')
numa_nodes.sort()
print(int(os.path.basename(numa_nodes[-1])[4:]) + 1)
else:
subprocess.run(['sysctl', '-n', 'vm.ndomains'], check=False)
elif os.name == 'nt':
libkernel32 = ctypes.windll.kernel32
numa_count = ctypes.c_ulong()
libkernel32.GetNumaHighestNodeNumber(ctypes.pointer(numa_count))
print(numa_count.value + 1)

View File

@ -16,6 +16,8 @@ echo = py3 + ['-c', 'import sys; print(*sys.argv[1:])']
list_dir_globs = py3 + files('list-dir-globs.py')
map_to_win_cmd = py3 + files('map_to_win.py')
sphinx_wrapper = py3 + files('call-sphinx-build.py')
get_cpu_count_cmd = py3 + files('get-cpu-count.py')
get_numa_count_cmd = py3 + files('get-numa-count.py')
# select library and object file format
pmdinfo = py3 + files('gen-pmdinfo-cfile.py') + [meson.current_build_dir()]

View File

@ -287,8 +287,6 @@ foreach arg: warning_flags
endforeach
# set other values pulled from the build options
dpdk_conf.set('RTE_MAX_LCORE', get_option('max_lcores'))
dpdk_conf.set('RTE_MAX_NUMA_NODES', get_option('max_numa_nodes'))
dpdk_conf.set('RTE_MAX_ETHPORTS', get_option('max_ethports'))
dpdk_conf.set('RTE_LIBEAL_USE_HPET', get_option('use_hpet'))
dpdk_conf.set('RTE_ENABLE_TRACE_FP', get_option('enable_trace_fp'))
@ -322,6 +320,51 @@ if meson.is_cross_build()
endif
endif
max_lcores = get_option('max_lcores')
if max_lcores == 'detect'
# discovery makes sense only for non-cross builds
if meson.is_cross_build()
error('Discovery of max_lcores is not supported for cross-compilation.')
endif
# overwrite the default value with discovered values
max_lcores = run_command(get_cpu_count_cmd).stdout().to_int()
min_lcores = 2
# DPDK must be built for at least 2 cores
if max_lcores < min_lcores
message('Found less than @0@ cores, building for @0@ cores'.format(min_lcores))
max_lcores = min_lcores
else
message('Found @0@ cores'.format(max_lcores))
endif
dpdk_conf.set('RTE_MAX_LCORE', max_lcores)
elif max_lcores != 'default'
# overwrite the default value from arch_subdir with user input
dpdk_conf.set('RTE_MAX_LCORE', max_lcores.to_int())
endif
max_numa_nodes = get_option('max_numa_nodes')
if max_numa_nodes == 'detect'
# discovery makes sense only for non-cross builds
if meson.is_cross_build()
error('Discovery of max_numa_nodes not supported for cross-compilation.')
endif
# overwrite the default value with discovered values
max_numa_nodes = run_command(get_numa_count_cmd).stdout().to_int()
message('Found @0@ numa nodes'.format(max_numa_nodes))
dpdk_conf.set('RTE_MAX_NUMA_NODES', max_numa_nodes)
elif max_numa_nodes != 'default'
# overwrite the default value from arch_subdir with user input
dpdk_conf.set('RTE_MAX_NUMA_NODES', max_numa_nodes.to_int())
endif
# check that CPU and NUMA counts are set
if not dpdk_conf.has('RTE_MAX_LCORE')
error('Number of CPU cores not specified.')
endif
if not dpdk_conf.has('RTE_MAX_NUMA_NODES')
error('Number of NUMA nodes not specified.')
endif
# set the install path for the drivers
dpdk_conf.set_quoted('RTE_EAL_PMD_PATH', eal_pmd_path)

View File

@ -70,3 +70,5 @@ else
endif
dpdk_conf.set('RTE_CACHE_LINE_SIZE', 64)
dpdk_conf.set('RTE_MAX_LCORE', 128)
dpdk_conf.set('RTE_MAX_NUMA_NODES', 32)

View File

@ -34,10 +34,10 @@ option('machine', type: 'string', value: 'auto', description:
'Alias of cpu_instruction_set.')
option('max_ethports', type: 'integer', value: 32, description:
'maximum number of Ethernet devices')
option('max_lcores', type: 'integer', value: 128, description:
'maximum number of cores/threads supported by EAL')
option('max_numa_nodes', type: 'integer', value: 32, description:
'maximum number of NUMA nodes supported by EAL')
option('max_lcores', type: 'string', value: 'default', description:
'Set maximum number of cores/threads supported by EAL; "default" is different per-arch, "detect" detects the number of cores on the build machine.')
option('max_numa_nodes', type: 'string', value: 'default', description:
'Set the highest NUMA node supported by EAL; "default" is different per-arch, "detect" detects the highest NUMA node on the build machine.')
option('platform', type: 'string', value: 'native', description:
'Platform to build, either "native", "generic" or a SoC. Please refer to the Linux build guide for more information.')
option('enable_trace_fp', type: 'boolean', value: false, description: