Received: by 2002:a05:6500:2018:b0:1fb:9675:f89d with SMTP id t24csp185657lqh; Thu, 30 May 2024 19:49:38 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCV3/9rgBky/ybXtewPuRpzTJqED8F7pUPbu43R2cwDuv6Em5gcX0/K0zhSpukMQLPT5Ry7lAGvVw+OU+a8SLIqJEhusR4vRPJ9iAfQeXA== X-Google-Smtp-Source: AGHT+IHw3GfMxWKjVFniIJ6dhtkdSHa0mVZv7sLGgEHOSnhoczX5ZkCGkChJv31I4kvXoFFhDGCB X-Received: by 2002:a05:6214:4991:b0:6ad:650a:855d with SMTP id 6a1803df08f44-6aecd6a08f0mr12881306d6.23.1717123778692; Thu, 30 May 2024 19:49:38 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1717123778; cv=pass; d=google.com; s=arc-20160816; b=l3yyQMfXHoHylQPCbJZQIHmHHWzsF1+fZ7mcOCj+rZcwHmbm+7JT+amlpwe1+V+yS2 KMKXMBOgEVsZn4UaNJm2RZHs0uQqjByc/57tdzhGK87RdQutGY/xZEDrFw/mv0hq3YTh w3EelBiejbtPY3piaxBzHwh434iNKBSG6CGI6Q8F8kij/1xdXodt4Q1Y4TC4uLeC0TiH eKhLKGwx8be28Eux43cRTuXRr4sdsHmWzLJ115uJtx56rrsQzrN7jYusd2JcJo1CwHf4 qTpjN5LSm4CPw5U7TIQdsYQylzfyIRtjCu9Z3hV82li4XZrOKN0eniL5u7YUhriRRoJY D6Hw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:date:subject:cc:to :from; bh=1JdTAd9y05TMg3TndvpjvIqXtOOkJQ2RjIXtXjCOxaE=; fh=QuN2PS/khznC/f5d7eCPqKkREuILwMpX0YAUc1N53gw=; b=gQRyeLFSywIIXErRknjsxgfNvAk4+wnavprL3ZAvsSUPer5iawmWin2Ua73MxfnOLb iFnAiK0YOlpPOR0LvJEL4/ZXKjxTZ7VwEGVZKvupFaD2BrZnWTBZEBUAfBhf7CzA2XT8 SOlcgaXNTecyVPE/JjjMjTl7tWPd43DuyQMtUEa3gDhgNcw5wIYP7SalC529XEAyCCA+ upJSZwLq9hyQuY2nC+Dkx/RlJGEzDnqhgs7VhxyAwFE3mt3XVVztBfBsLMHPmYebbzFN dXnSec1JUv3Q7SokX1krSR/TSqEmhXNsUkp0gCUrs7M2Os+Zu9sESGpEyVZSDFHqQcrE RMFA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=sina.com); spf=pass (google.com: domain of linux-kernel+bounces-196199-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-196199-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id 6a1803df08f44-6ae4b403b94si10967366d6.190.2024.05.30.19.49.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 May 2024 19:49:38 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-196199-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=sina.com); spf=pass (google.com: domain of linux-kernel+bounces-196199-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-196199-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 5D9F61C239A5 for ; Fri, 31 May 2024 02:49:38 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 35C1078297; Fri, 31 May 2024 02:49:27 +0000 (UTC) Received: from r3-11.sinamail.sina.com.cn (r3-11.sinamail.sina.com.cn [202.108.3.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 35B9B78C7A for ; Fri, 31 May 2024 02:49:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.108.3.11 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717123766; cv=none; b=QgfROSjVy6ANjzqwtQrIyS3K7frgQs/VrlrM7aRF+4o7rCrpaMsyP234rz3EPZkB4pbPZ+evd8E6EmK3nMMZFgRmtTN6qZ/CkbqwrnyUycSp+D2iAeh4uyQWsRTR6mzjWww53HLShsMKvhAuUnuioRB0nDLRFawku4lsLOzPJt8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717123766; c=relaxed/simple; bh=yC+LB2Y6jUoQAATr+h19M50CQIqqD4nkhuJXFLuUmIk=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=jgj0NArw22IWj2VJ1tghXDz1YydgoNrS1MlZ41GkR/gXEwkIl0SBslcWGauJX+cmmDRfu0hDuEST0qDljSTCrf3M9N/FI+2y/xBWoPQ0I8My7CpeSzyyBkzTP4TgkIlWgNAvVHGtGwfOsYVfVfcuqcgNFD3I4M2ODElHCWX1sCw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=sina.com; spf=pass smtp.mailfrom=sina.com; arc=none smtp.client-ip=202.108.3.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=sina.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sina.com X-SMAIL-HELO: localhost Received: from unknown (HELO localhost)([101.132.132.191]) by sina.com (10.182.253.22) with ESMTP id 66593A8700000D3E; Fri, 31 May 2024 10:48:41 +0800 (CST) X-Sender: ghostxavier@sina.com X-Auth-ID: ghostxavier@sina.com Authentication-Results: sina.com; spf=none smtp.mailfrom=ghostxavier@sina.com; dkim=none header.i=none; dmarc=none action=none header.from=ghostxavier@sina.com X-SMAIL-MID: 2472246816138 X-SMAIL-UIID: C36FAEE0ECE84822B888075C91066179-20240531-104841-1 From: Xavier To: longman@redhat.com, lizefan.x@bytedance.com, tj@kernel.org, hannes@cmpxchg.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Xavier Subject: [PATCH v2] cpuset: Optimize the number of iterations in the scheduling domain construction process Date: Fri, 31 May 2024 10:48:37 +0800 Message-Id: <20240531024837.255293-1-ghostxavier@sina.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The process of constructing scheduling domains involves multiple loops and repeated evaluations, leading to numerous redundant and ineffective assessments that impact code efficiency. Here, we use Union-Find to optimize the merging of cpumasks. By employing path compression and union by rank, we effectively reduce the number of lookups and merge comparisons. Signed-off-by: Xavier --- kernel/cgroup/cpuset.c | 117 +++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 51 deletions(-) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index c12b9fdb2..4bea1c2db 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -891,6 +891,44 @@ static inline int nr_cpusets(void) return static_key_count(&cpusets_enabled_key.key) + 1; } +/*define a union find node struct*/ +struct uf_node { + int parent; + int rank; +}; + +static int find_root(struct uf_node *nodes, int x) +{ + int root = x; + int parent; + + /*Find the root node and perform path compression at the same time*/ + while (nodes[root].parent != root) { + parent = nodes[root].parent; + nodes[root].parent = nodes[parent].parent; + root = parent; + } + return root; +} + +/*Function to merge two sets, using union by rank*/ +static void union_sets(struct uf_node *nodes, int a, int b) +{ + int root_a = find_root(nodes, a); + int root_b = find_root(nodes, b); + + if (root_a != root_b) { + if (nodes[root_a].rank < nodes[root_b].rank) { + nodes[root_a].parent = root_b; + } else if (nodes[root_a].rank > nodes[root_b].rank) { + nodes[root_b].parent = root_a; + } else { + nodes[root_b].parent = root_a; + nodes[root_a].rank++; + } + } +} + /* * generate_sched_domains() * @@ -950,13 +988,14 @@ static int generate_sched_domains(cpumask_var_t **domains, struct cpuset *cp; /* top-down scan of cpusets */ struct cpuset **csa; /* array of all cpuset ptrs */ int csn; /* how many cpuset ptrs in csa so far */ - int i, j, k; /* indices for partition finding loops */ + int i, j; /* indices for partition finding loops */ cpumask_var_t *doms; /* resulting partition; i.e. sched domains */ struct sched_domain_attr *dattr; /* attributes for custom domains */ int ndoms = 0; /* number of sched domains in result */ int nslot; /* next empty doms[] struct cpumask slot */ struct cgroup_subsys_state *pos_css; bool root_load_balance = is_sched_load_balance(&top_cpuset); + struct uf_node *nodes; doms = NULL; dattr = NULL; @@ -1022,33 +1061,31 @@ static int generate_sched_domains(cpumask_var_t **domains, } rcu_read_unlock(); - for (i = 0; i < csn; i++) - csa[i]->pn = i; - ndoms = csn; - -restart: - /* Find the best partition (set of sched domains) */ - for (i = 0; i < csn; i++) { - struct cpuset *a = csa[i]; - int apn = a->pn; + nodes = kmalloc_array(csn, sizeof(struct uf_node), GFP_KERNEL); + if (!nodes) + goto done; - for (j = 0; j < csn; j++) { - struct cpuset *b = csa[j]; - int bpn = b->pn; - if (apn != bpn && cpusets_overlap(a, b)) { - for (k = 0; k < csn; k++) { - struct cpuset *c = csa[k]; + /* Each node is initially its own parent */ + for (i = 0; i < csn; i++) { + nodes[i].parent = i; + nodes[i].rank = 0; + } - if (c->pn == bpn) - c->pn = apn; - } - ndoms--; /* one less element */ - goto restart; - } + /* Merge overlapping cpusets */ + for (i = 0; i < csn; i++) { + for (j = i + 1; j < csn; j++) { + if (cpusets_overlap(csa[i], csa[j])) + union_sets(nodes, i, j); } } + /* Calculate the number of domains after merging */ + for (i = 0; i < csn; i++) { + if (nodes[i].parent == i) + ndoms++; + } + /* * Now we know how many domains to create. * Convert to and populate cpu masks. @@ -1065,47 +1102,25 @@ static int generate_sched_domains(cpumask_var_t **domains, GFP_KERNEL); for (nslot = 0, i = 0; i < csn; i++) { - struct cpuset *a = csa[i]; - struct cpumask *dp; - int apn = a->pn; - - if (apn < 0) { - /* Skip completed partitions */ - continue; - } - - dp = doms[nslot]; - - if (nslot == ndoms) { - static int warnings = 10; - if (warnings) { - pr_warn("rebuild_sched_domains confused: nslot %d, ndoms %d, csn %d, i %d, apn %d\n", - nslot, ndoms, csn, i, apn); - warnings--; - } - continue; - } + struct cpumask *dp = doms[nslot]; cpumask_clear(dp); if (dattr) *(dattr + nslot) = SD_ATTR_INIT; for (j = i; j < csn; j++) { - struct cpuset *b = csa[j]; + if (find_root(nodes, j) == i) { + if (i == j) + nslot++; - if (apn == b->pn) { - cpumask_or(dp, dp, b->effective_cpus); + cpumask_or(dp, dp, csa[j]->effective_cpus); cpumask_and(dp, dp, housekeeping_cpumask(HK_TYPE_DOMAIN)); if (dattr) - update_domain_attr_tree(dattr + nslot, b); - - /* Done with this partition */ - b->pn = -1; + update_domain_attr_tree(dattr + nslot, csa[j]); } } - nslot++; } BUG_ON(nslot != ndoms); - + kfree(nodes); done: kfree(csa); -- 2.34.1