Received: by 2002:a25:d7c1:0:0:0:0:0 with SMTP id o184csp3911196ybg; Mon, 21 Oct 2019 00:23:09 -0700 (PDT) X-Google-Smtp-Source: APXvYqx3ykMjMtp3fQBXoAES16hhct8u3sydzf+smANzJimu5kcrPwoVVWc3xPZ1mbDoJQ85zDwr X-Received: by 2002:a17:907:20b3:: with SMTP id pw19mr20367758ejb.76.1571642589812; Mon, 21 Oct 2019 00:23:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571642589; cv=none; d=google.com; s=arc-20160816; b=ezOwvFxe8e+QUkMrSOzgSiINHkreAL2nV0F2JvkWX+NmpnZSWtnmciu1mN83xanUow BkUZz/FlVsHnyZnZu5s2wL8TDOEmkUcKwEDN/ZD+u4tAO1boAu9mQjsvw8VZ5R2MC+Nh VReRrOrLuxRqZh43Wryq7So+1KynByr3NPTvfzltRpTJWzWGBrph3DHdnoVYELXiwTFZ 9VVaNNaReElvz73jP+MTyIvL8o5v7nwmEF08iUHTvdwqSudjqxfoRDqsxUEjWOMPYnDl dJPEehjBtZjiUoICIPj8yYPBW9UPOXW2UsCrkEDqQCpj1i87bk9OckvgInwZXtjqzPmu H2qA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:in-reply-to :mime-version:user-agent:date:message-id:from:cc:references:to :subject; bh=FKUmZnVhLlu05HR31mSiVFT7CjXVj8DcaPBge69dmaA=; b=E4wCUYwr6Jt0mDgF5K4CyIg15YpFsmugonA3G0KWS4r9/VJTDp83UBBRJlyOIUTF9A fWMzJ2yKLFYp0iBiq3aFIkwedKs/Wc6B2/PPSUVqaIRXQHafGv/Vnen2pnMHSF6WqxrP m2ZFIe1XgxkFKdAhuBunZZmKPWCiVkJ9ILcemHvo68zyCXmV8hut+R9rixKJeOxNQEiu 3iJTvksT59ymADSQqesvkOJb9aYMVgxthHqMb++IVOqocbW1cxsve0+DfKPoAB3Rqm2F bCD+uvw5vlXngOhAfHm7OpTpsQEG7RPu3e0vPJoXOx9FMv6Q4+BdTYrG1HOye0vHnt6/ S4Rw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v12si9292660edf.212.2019.10.21.00.22.45; Mon, 21 Oct 2019 00:23:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727332AbfJUHWU (ORCPT + 99 others); Mon, 21 Oct 2019 03:22:20 -0400 Received: from szxga07-in.huawei.com ([45.249.212.35]:36538 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726480AbfJUHWU (ORCPT ); Mon, 21 Oct 2019 03:22:20 -0400 Received: from DGGEMS410-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 38ACE34F3F7D61CA77E1; Mon, 21 Oct 2019 15:22:17 +0800 (CST) Received: from [127.0.0.1] (10.74.221.148) by DGGEMS410-HUB.china.huawei.com (10.3.19.210) with Microsoft SMTP Server id 14.3.439.0; Mon, 21 Oct 2019 15:22:08 +0800 Subject: Re: [RFC] lib: optimize cpumask_local_spread() To: Michal Hocko References: <1571307788-43169-1-git-send-email-zhangshaokun@hisilicon.com> <20191017123734.GJ24485@dhcp22.suse.cz> CC: , yuqi jin , "Andrew Morton" , Mike Rapoport , "Paul Burton" , Michael Ellerman , Anshuman Khandual From: Shaokun Zhang Message-ID: Date: Mon, 21 Oct 2019 15:22:08 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20191017123734.GJ24485@dhcp22.suse.cz> Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.74.221.148] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Michal, On 2019/10/17 20:37, Michal Hocko wrote: > On Thu 17-10-19 18:23:08, Shaokun Zhang wrote: >> From: yuqi jin >> >> In the multi-processor and NUMA system, A device may have many numa >> nodes belonging to multiple cpus. When we get a local numa, it is better >> to find the node closest to the local numa node to return instead of >> going to the online cpu immediately. >> >> For example, In Huawei Kunpeng 920 system, there are 4 NUMA node(0 -3) >> in the 2-socket system(0 - 1). If the I/O device is in socket1 >> and the local NUMA node is 2, we shall choose the non-local node3 in >> the same socket when cpu core in NUMA node2 is less that I/O requirements. >> If we directly pick one cpu core from all online ones, it may be in >> the another socket and it is not friendly for performance. > > Could you be more specific on the effect of this patch please? Do you > have any performance numbers? The NIC driver calls this function to determine the core which irq will be binded to, and the initialization of XPS depends on the binding of irqs. The NIC driver will get the local NUMA node where it is located. On Huawei Kunpeng 920 SoC, there are 4-NUMA nodes and there is 24-cores per node. If the function paratmer @i = 0-23 and @node = 2, then the core which is located on node 2 and irq will be binded to node2. If the parameter @i = 24-47 and @node = 2, without this patch, it will return the core which is on NUMA node0; Applied the patch, it will return NUMA node3 cpu cores which are in the same sokcet. without the patch, the performance is 22W QPS and added this patch, the performance become better and it is 26W QPS. I'm not sure whether anyone also hits this problem and send it as a RFC. > Also is it safe and reasonable to perform GFP_KERNEL (aka sleepable) > allocations from this function? > Good catch, I missed it and it should be GFP_ATOMIC. Thanks, Shaokun. >> Cc: Andrew Morton >> Cc: Mike Rapoport >> Cc: Paul Burton >> Cc: Michal Hocko >> Cc: Michael Ellerman >> Cc: Anshuman Khandual >> Signed-off-by: yuqi jin >> Signed-off-by: Shaokun Zhang >> --- >> lib/cpumask.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- >> 1 file changed, 67 insertions(+), 11 deletions(-) >> >> diff --git a/lib/cpumask.c b/lib/cpumask.c >> index 0cb672eb107c..8f89c7cebfb0 100644 >> --- a/lib/cpumask.c >> +++ b/lib/cpumask.c >> @@ -192,6 +192,33 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask) >> } >> #endif >> >> +static void calc_node_distance(int *node_dist, int node) >> +{ >> + int i; >> + >> + for (i = 0; i < nr_node_ids; i++) >> + node_dist[i] = node_distance(node, i); >> +} >> + >> +static int find_nearest_node(int *node_dist, bool *used_flag) >> +{ >> + int i, min_dist = node_dist[0], node_id = -1; >> + >> + for (i = 0; i < nr_node_ids; i++) >> + if (used_flag[i] == 0) { >> + min_dist = node_dist[i]; >> + node_id = i; >> + break; >> + } >> + for (i = 0; i < nr_node_ids; i++) >> + if (node_dist[i] < min_dist && used_flag[i] == 0) { >> + min_dist = node_dist[i]; >> + node_id = i; >> + } >> + >> + return node_id; >> +} >> + >> /** >> * cpumask_local_spread - select the i'th cpu with local numa cpu's first >> * @i: index number >> @@ -205,7 +232,8 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask) >> */ >> unsigned int cpumask_local_spread(unsigned int i, int node) >> { >> - int cpu; >> + int cpu, j, id, *node_dist; >> + bool *used_flag; >> >> /* Wrap: we always want a cpu. */ >> i %= num_online_cpus(); >> @@ -215,19 +243,47 @@ unsigned int cpumask_local_spread(unsigned int i, int node) >> if (i-- == 0) >> return cpu; >> } else { >> - /* NUMA first. */ >> - for_each_cpu_and(cpu, cpumask_of_node(node), cpu_online_mask) >> - if (i-- == 0) >> - return cpu; >> + node_dist = kmalloc_array(nr_node_ids, >> + sizeof(int), GFP_KERNEL); >> + if (!node_dist) >> + for_each_cpu(cpu, cpu_online_mask) >> + if (i-- == 0) >> + return cpu; >> >> - for_each_cpu(cpu, cpu_online_mask) { >> - /* Skip NUMA nodes, done above. */ >> - if (cpumask_test_cpu(cpu, cpumask_of_node(node))) >> - continue; >> + used_flag = kmalloc_array(nr_node_ids, >> + sizeof(bool), GFP_KERNEL); >> + if (!used_flag) >> + for_each_cpu(cpu, cpu_online_mask) >> + if (i-- == 0) { >> + kfree(node_dist); >> + return cpu; >> + } >> + memset(used_flag, 0, nr_node_ids * sizeof(bool)); >> >> - if (i-- == 0) >> - return cpu; >> + calc_node_distance(node_dist, node); >> + for (j = 0; j < nr_node_ids; j++) { >> + id = find_nearest_node(node_dist, used_flag); >> + if (id < 0) >> + break; >> + for_each_cpu_and(cpu, >> + cpumask_of_node(id), cpu_online_mask) >> + if (i-- == 0) { >> + kfree(node_dist); >> + kfree(used_flag); >> + return cpu; >> + } >> + used_flag[id] = 1; >> } >> + >> + for_each_cpu(cpu, cpu_online_mask) >> + if (i-- == 0) { >> + kfree(node_dist); >> + kfree(used_flag); >> + return cpu; >> + } >> + >> + kfree(node_dist); >> + kfree(used_flag); >> } >> BUG(); >> } >> -- >> 2.7.4 >