MINOR: cpu-topo: add a new "resource" cpu-policy

This cpu policy keeps the smallest CPU cluster. This can
be used to limit the resource usage to the strict minimum
that still delivers decent performance, for example to
try to further reduce power consumption or minimize the
number of cores needed on some rented systems for a
sidecar setup, in order to scale the system down more
easily. Note that if a single cluster is present, it
will still be fully used.

When started on a 64-core EPYC gen3, it uses only one CCX
with 8 cores and 16 threads, all in the same group.
This commit is contained in:
Willy Tarreau 2025-03-14 18:16:52 +01:00
parent ad3650c354
commit e3fd9970a9
2 changed files with 50 additions and 0 deletions

View File

@ -2014,6 +2014,17 @@ cpu-policy <policy>
systems, these can also be used to run auxiliary tools
such as load generators and monitoring tools.
- resource this is like group-by-cluster above, except that only
the smallest and most efficient CPU cluster will be
used, while all other ones will be ignored. This can be
used to limit the resource usage to the strict minimum
that still delivers decent performance, for example to
try to further reduce power consumption or minimize the
number of cores needed on some rented systems for a
sidecar setup, in order to scale the system down more
easily. Note that if a single cluster is present, it
will still be fully used.
See also: "cpu-map", "cpu-set", "nbthread"
cpu-set <directive>...

View File

@ -55,6 +55,7 @@ static int cpu_policy_first_usable_node(int policy, int tmin, int tmax, int gmin
static int cpu_policy_group_by_cluster(int policy, int tmin, int tmax, int gmin, int gmax, char **err);
static int cpu_policy_performance(int policy, int tmin, int tmax, int gmin, int gmax, char **err);
static int cpu_policy_efficiency(int policy, int tmin, int tmax, int gmin, int gmax, char **err);
static int cpu_policy_resource(int policy, int tmin, int tmax, int gmin, int gmax, char **err);
static struct ha_cpu_policy ha_cpu_policy[] = {
{ .name = "none", .desc = "use all available CPUs", .fct = NULL },
@ -62,6 +63,7 @@ static struct ha_cpu_policy ha_cpu_policy[] = {
{ .name = "group-by-cluster", .desc = "make one thread group per core cluster", .fct = cpu_policy_group_by_cluster },
{ .name = "performance", .desc = "make one thread group per perf. core cluster", .fct = cpu_policy_performance },
{ .name = "efficiency", .desc = "make one thread group per eff. core cluster", .fct = cpu_policy_efficiency },
{ .name = "resource", .desc = "make one thread group from the smallest cluster", .fct = cpu_policy_resource },
{ 0 } /* end */
};
@ -1176,6 +1178,43 @@ static int cpu_policy_efficiency(int policy, int tmin, int tmax, int gmin, int g
return cpu_policy_group_by_cluster(policy, tmin, tmax, gmin, gmax, err);
}
/* the "resource" cpu-policy:
* - does nothing if nbthread or thread-groups are set
* - only keeps the smallest cluster.
*/
static int cpu_policy_resource(int policy, int tmin, int tmax, int gmin, int gmax, char **err)
{
int cpu, cluster;
int capa;
if (global.nbthread || global.nbtgroups)
return 0;
/* sort clusters by reverse capacity */
cpu_cluster_reorder_by_capa(ha_cpu_clusters, cpu_topo_maxcpus);
capa = 0;
for (cluster = cpu_topo_maxcpus - 1; cluster >= 0; cluster--) {
if (capa) {
/* we already have a cluster, let's disable this
* one.
*/
for (cpu = 0; cpu <= cpu_topo_lastcpu; cpu++) {
if (ha_cpu_topo[cpu].cl_gid == ha_cpu_clusters[cluster].idx)
ha_cpu_topo[cpu].st |= HA_CPU_F_IGNORED;
}
}
else
capa = ha_cpu_clusters[cluster].capa;
}
cpu_cluster_reorder_by_index(ha_cpu_clusters, cpu_topo_maxcpus);
/* and finish using the group-by-cluster strategy */
return cpu_policy_group_by_cluster(policy, tmin, tmax, gmin, gmax, err);
}
/* apply the chosen CPU policy if no cpu-map was forced. Returns < 0 on failure
* with a message in *err that must be freed by the caller if non-null.
*/