From 5fbe9a94ebcc7463bbe9a77fea3577a844c55ec5 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Tue, 13 Sep 2022 13:04:18 -0400 Subject: [PATCH 1/7] [DNM] Force packing as a test --- placement.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/placement.c b/placement.c index 73d87c7..185aa0d 100644 --- a/placement.c +++ b/placement.c @@ -120,11 +120,11 @@ static void find_best_object_for_irq(struct irq_info *info, void *data) place.best = NULL; place.best_cost = ULLONG_MAX; - if (info->level != BALANCE_CORE) { - for_each_object(d->children, find_best_object, &place); - } else { + //if (info->level != BALANCE_CORE) { + // for_each_object(d->children, find_best_object, &place); + //} else { find_best_object_packing(d->children, info, &place); - } + //} asign = place.best; From db3506f4dd98e103ae6d9d2c66329156e40a93a9 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Thu, 15 Sep 2022 18:52:51 -0400 Subject: [PATCH 2/7] [DNM] Implement packing for all balancing levels --- cputree.c | 8 ++++++++ numa.c | 3 ++- placement.c | 10 +++++----- types.h | 1 + 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/cputree.c b/cputree.c index eb1981e..37c074b 100644 --- a/cputree.c +++ b/cputree.c @@ -224,11 +224,13 @@ static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache, package->obj_type = OBJ_TYPE_PACKAGE; package->obj_type_list = &packages; package->number = packageid; + package->max_load = 0; packages = g_list_append(packages, package); } entry = g_list_find(package->children, cache); if (!entry) { + package->max_load += cache->max_load; package->children = g_list_append(package->children, cache); cache->parent = package; } @@ -264,12 +266,14 @@ static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu, cache->mask = cache_mask; cache->number = cache_domain_count; cache->obj_type_list = &cache_domains; + cache->max_load = 0; cache_domains = g_list_append(cache_domains, cache); cache_domain_count++; } entry = g_list_find(cache->children, cpu); if (!entry) { + cache->max_load += cpu->max_load; cache->children = g_list_append(cache->children, cpu); cpu->parent = (struct topo_obj *)cache; } @@ -317,6 +321,8 @@ static void do_one_cpu(char *path) cpu->number = strtoul(&path[27], NULL, 10); + cpu->max_load = SLEEP_INTERVAL * 1000 * 1000; // SLEEP_INTERVAL in nanoseconds, should be a good enough approximation + cpu_set(cpu->number, cpu_online_map); cpu_set(cpu->number, cpu->mask); @@ -398,6 +404,8 @@ static void do_one_cpu(char *path) * we override package_mask with node mask. */ node = get_numa_node(nodeid); + if (node) + node->max_load += cpu->max_load; if (node && (cpus_weight(package_mask) > cpus_weight(node->mask))) cpus_and(package_mask, package_mask, node->mask); } diff --git a/numa.c b/numa.c index 13d7ebd..c710f98 100644 --- a/numa.c +++ b/numa.c @@ -58,9 +58,10 @@ static void add_one_node(int nodeid) process_one_line(path, get_mask_from_bitmap, &new->mask); } - new->obj_type = OBJ_TYPE_NODE; + new->obj_type = OBJ_TYPE_NODE; new->number = nodeid; new->obj_type_list = &numa_nodes; + new->max_load = 0; numa_nodes = g_list_append(numa_nodes, new); } diff --git a/placement.c b/placement.c index 185aa0d..c78673b 100644 --- a/placement.c +++ b/placement.c @@ -76,7 +76,7 @@ static void find_best_object_packing(GList *objs, struct irq_info *info, struct entry = g_list_first(objs); while (entry) { struct topo_obj *d = entry->data; - if (d->load + info->load < 0.9e9) { + if (d->load + info->load < d->max_load) { place->best = d; place->best_cost = d->load + info->load; return; @@ -120,11 +120,11 @@ static void find_best_object_for_irq(struct irq_info *info, void *data) place.best = NULL; place.best_cost = ULLONG_MAX; - //if (info->level != BALANCE_CORE) { - // for_each_object(d->children, find_best_object, &place); - //} else { + if (info->level != BALANCE_CORE) { + for_each_object(d->children, find_best_object, &place); + } else { find_best_object_packing(d->children, info, &place); - //} + } asign = place.best; diff --git a/types.h b/types.h index 9693cf4..c26344c 100644 --- a/types.h +++ b/types.h @@ -46,6 +46,7 @@ enum obj_type_e { struct topo_obj { uint64_t load; uint64_t last_load; + uint64_t max_load; uint64_t irq_count; enum obj_type_e obj_type; int number; From 69d0a87e2f477a64e52ee0d701c3590cac7dd5ac Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Fri, 16 Sep 2022 14:50:50 -0400 Subject: [PATCH 3/7] [DNM] cputree: add max_load to debug output --- cputree.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cputree.c b/cputree.c index 37c074b..791b0bc 100644 --- a/cputree.c +++ b/cputree.c @@ -453,7 +453,7 @@ static void dump_balance_obj(struct topo_obj *d, void *data __attribute__((unuse log(TO_CONSOLE, LOG_INFO, "%s%s%s%sCPU number %i numa_node is ", log_indent, log_indent, log_indent, log_indent, c->number); for_each_object(cpu_numa_node(c), dump_numa_node_num, NULL); - log(TO_CONSOLE, LOG_INFO, "(load %lu)\n", (unsigned long)c->load); + log(TO_CONSOLE, LOG_INFO, "(load %lu, max %lu)\n", (unsigned long)c->load, (unsigned long)c->max_load); if (c->interrupts) for_each_irq(c->interrupts, dump_irq, (void *)18); } @@ -465,8 +465,8 @@ static void dump_cache_domain(struct topo_obj *d, void *data) log(TO_CONSOLE, LOG_INFO, "%s%sCache domain %i: numa_node is ", log_indent, log_indent, d->number); for_each_object(d->numa_nodes, dump_numa_node_num, NULL); - log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu) \n", buffer, - (unsigned long)d->load); + log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu, max %lu) \n", buffer, + (unsigned long)d->load, (unsigned long)d->max_load); if (d->children) for_each_object(d->children, dump_balance_obj, NULL); if (g_list_length(d->interrupts) > 0) @@ -479,8 +479,8 @@ static void dump_package(struct topo_obj *d, void *data) cpumask_scnprintf(buffer, 4096, d->mask); log(TO_CONSOLE, LOG_INFO, "Package %i: numa_node ", d->number); for_each_object(d->numa_nodes, dump_numa_node_num, NULL); - log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu)\n", - buffer, (unsigned long)d->load); + log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu, max %lu)\n", + buffer, (unsigned long)d->load, (unsigned long)d->max_load); if (d->children) for_each_object(d->children, dump_cache_domain, buffer); if (g_list_length(d->interrupts) > 0) From c6d270495cf6872bcb252dcddaa054eb3e3fbe3b Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Fri, 16 Sep 2022 17:04:28 -0400 Subject: [PATCH 4/7] [DNM] cputree: correct conversion to nanoseconds --- cputree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cputree.c b/cputree.c index 791b0bc..c195ec9 100644 --- a/cputree.c +++ b/cputree.c @@ -321,7 +321,7 @@ static void do_one_cpu(char *path) cpu->number = strtoul(&path[27], NULL, 10); - cpu->max_load = SLEEP_INTERVAL * 1000 * 1000; // SLEEP_INTERVAL in nanoseconds, should be a good enough approximation + cpu->max_load = SLEEP_INTERVAL * 1000 * 1000 * 1000; // SLEEP_INTERVAL in nanoseconds, should be a good enough approximation cpu_set(cpu->number, cpu_online_map); From 7218ded6d7ad8cbaa95beb30f0b6a97aa2f961ee Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Fri, 16 Sep 2022 17:10:27 -0400 Subject: [PATCH 5/7] [DNM] placement: ignore banned NUMA nodes --- placement.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/placement.c b/placement.c index c78673b..d2cdace 100644 --- a/placement.c +++ b/placement.c @@ -76,6 +76,21 @@ static void find_best_object_packing(GList *objs, struct irq_info *info, struct entry = g_list_first(objs); while (entry) { struct topo_obj *d = entry->data; + + /* + * Don't consider the unspecified numa node here + */ + if (numa_avail && (d->obj_type == OBJ_TYPE_NODE) && (d->number == NUMA_NO_NODE)) + continue; + + /* + * also don't consider any node that doesn't have at least one cpu in + * the unbanned list + */ + if ((d->obj_type == OBJ_TYPE_NODE) && + (!cpus_intersects(d->mask, unbanned_cpus))) + continue; + if (d->load + info->load < d->max_load) { place->best = d; place->best_cost = d->load + info->load; From cbdb399e6d9a93aa9ae7fa1aa07e98b19009b7c8 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Fri, 16 Sep 2022 20:59:13 -0400 Subject: [PATCH 6/7] [DNM] irqlist: initial implementation for migration condition for packing --- irqlist.c | 24 +++++++++++++++++++++++- placement.c | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/irqlist.c b/irqlist.c index 4dd4a83..d18261c 100644 --- a/irqlist.c +++ b/irqlist.c @@ -79,7 +79,7 @@ static void move_candidate_irqs(struct irq_info *info, void *data) unsigned long delta_load = 0; /* Don't rebalance irqs that don't want it */ - if (info->level == BALANCE_NONE) + if (info->level == BALANCE_NONE || info->level == BALANCE_CORE) return; /* Don't move cpus that only have one irq, regardless of load */ @@ -113,6 +113,27 @@ static void move_candidate_irqs(struct irq_info *info, void *data) info->assigned_obj = NULL; } +static void move_candidate_irqs_packing(GList *irqs, struct topo_obj *obj, struct load_balance_info *lb_info) +{ + GList *entry; + entry = g_list_last(irqs); + while (entry) { + struct irq_info *info = entry->data; + + // Only pack BALANCE_CORE irqs + if (info->level != BALANCE_CORE) + continue; + + + if (lb_info->adjustment_load >= obj->max_load / 10 * 9) { + lb_info->adjustment_load -= info->load; + migrate_irq(&info->assigned_obj->interrupts, &rebalance_irq_list, info); + } + + entry = g_list_previous(entry); + } +} + static void migrate_overloaded_irqs(struct topo_obj *obj, void *data) { struct load_balance_info *info = data; @@ -143,6 +164,7 @@ static void migrate_overloaded_irqs(struct topo_obj *obj, void *data) */ info->adjustment_load = obj->load; for_each_irq(obj->interrupts, move_candidate_irqs, info); + move_candidate_irqs_packing(obj->interrupts, obj, info); } } diff --git a/placement.c b/placement.c index d2cdace..2ba2cc4 100644 --- a/placement.c +++ b/placement.c @@ -91,7 +91,7 @@ static void find_best_object_packing(GList *objs, struct irq_info *info, struct (!cpus_intersects(d->mask, unbanned_cpus))) continue; - if (d->load + info->load < d->max_load) { + if (d->load + info->load < d->max_load / 10 * 9) { place->best = d; place->best_cost = d->load + info->load; return; From 72e86f5ef6bb93652ec92a275d0753b21f4f1f70 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Mon, 19 Sep 2022 17:09:14 -0400 Subject: [PATCH 7/7] [DNM] Add log for packing --- irqlist.c | 1 + 1 file changed, 1 insertion(+) diff --git a/irqlist.c b/irqlist.c index d18261c..a3c9bcc 100644 --- a/irqlist.c +++ b/irqlist.c @@ -127,6 +127,7 @@ static void move_candidate_irqs_packing(GList *irqs, struct topo_obj *obj, struc if (lb_info->adjustment_load >= obj->max_load / 10 * 9) { lb_info->adjustment_load -= info->load; + log(TO_CONSOLE, LOG_INFO, "Selecting irq %d for rebalancing via packing\n", info->irq); migrate_irq(&info->assigned_obj->interrupts, &rebalance_irq_list, info); }