]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cpu-topo: assign an L3 cache if more than 2 L2 instances
authorWilly Tarreau <w@1wt.eu>
Thu, 27 Feb 2025 18:22:34 +0000 (19:22 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 14 Mar 2025 17:30:31 +0000 (18:30 +0100)
On some machines, L3 is not always reported (e.g. on some lx2 or some
armada8040). But some also don't have L3 (core 2 quad). However, no L3
when there are more than 2 L2 is quite unheard of, and while we don't
really care about firing 2 thread groups for 2 L2, we'd rather avoid
doing this if there are 8! In this case we'll declare an L3 instance
to fix the situation. This allows small machines to continue to start
with two groups while not derivating on large ones.

src/cpu_topo.c

index 374efe923f586b76bc73f45cda3ace4965e309dd..ffca19ea2bc9046618e414ec3e74530bd83805fb 100644 (file)
@@ -422,7 +422,8 @@ static int cpu_topo_get_maxcpus(void)
 void cpu_fixup_topology(void)
 {
        struct hap_cpuset cpuset;
-       int cpu;
+       int cpu, cpu2;
+       int curr_id, prev_id;
        int min_id, neg;
 
        /* fill the package id, node id and thread_id. First we'll build a bitmap
@@ -504,6 +505,49 @@ void cpu_fixup_topology(void)
                if (ha_cpu_topo[cpu].capa < 0)
                        ha_cpu_topo[cpu].capa = (ha_cpu_topo[cpu].th_cnt > 1) ? 100 : 50;
        }
+
+       /* First, on some machines, L3 is not reported. But some also don't
+        * have L3.  However, no L3 when there are more than 2 L2 is quite
+        * unheard of, and while we don't really care about firing 2 groups for
+        * 2 L2, we'd rather avoid this if there are 8! In this case we'll add
+        * an L3 instance to fix the situation.
+        */
+       cpu_reorder_by_locality(ha_cpu_topo, cpu_topo_maxcpus);
+
+       prev_id = -2; // make sure it cannot match even unassigned ones
+       curr_id = -1;
+       for (cpu = cpu2 = 0; cpu <= cpu_topo_lastcpu; cpu++) {
+               if (ha_cpu_topo[cpu].ca_id[3] >= 0)
+                       continue;
+
+               /* L3 not assigned, count L2 instances */
+               if (!cpu ||
+                   (ha_cpu_topo[cpu].pk_id != ha_cpu_topo[cpu-1].pk_id) ||
+                   (ha_cpu_topo[cpu].no_id != ha_cpu_topo[cpu-1].no_id) ||
+                   (ha_cpu_topo[cpu].ca_id[4] != ha_cpu_topo[cpu-1].ca_id[4])) {
+                       curr_id = 0;
+                       prev_id = -2;
+                       cpu2 = cpu;
+               }
+               else if (ha_cpu_topo[cpu].ca_id[2] != prev_id) {
+                       curr_id++;
+                       if (curr_id >= 2) {
+                               /* let's assign L3 id to zero for all those.
+                                * We can go till the end since we'll just skip
+                                * them on next passes above.
+                                */
+                               for (; cpu2 <= cpu_topo_lastcpu; cpu2++) {
+                                       if (ha_cpu_topo[cpu2].ca_id[3] < 0 &&
+                                           ha_cpu_topo[cpu2].pk_id == ha_cpu_topo[cpu].pk_id &&
+                                           ha_cpu_topo[cpu2].no_id == ha_cpu_topo[cpu].no_id &&
+                                           ha_cpu_topo[cpu2].ca_id[4] == ha_cpu_topo[cpu].ca_id[4])
+                                               ha_cpu_topo[cpu2].ca_id[3] = 0;
+                               }
+                       }
+               }
+       }
+
+       cpu_reorder_by_index(ha_cpu_topo, cpu_topo_maxcpus);
 }
 
 /* This function is responsible for composing clusters based on existing info