From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S967770AbcA1WaA (ORCPT ); Thu, 28 Jan 2016 17:30:00 -0500 Received: from mail-pa0-f67.google.com ([209.85.220.67]:33852 "EHLO mail-pa0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965255AbcA1W36 (ORCPT ); Thu, 28 Jan 2016 17:29:58 -0500 Message-ID: <1454020194.7627.48.camel@edumazet-glaptop2.roam.corp.google.com> Subject: Re: [PATCH] Optimize int_sqrt for small values for faster idle From: Eric Dumazet To: Andi Kleen Cc: akpm@linux-foundation.org, linux-kernel@vger.kernel.org, davidlohr.bueso@hp.com, rafael.j.wysocki@intel.com, lenb@kernel.org, Andi Kleen Date: Thu, 28 Jan 2016 14:29:54 -0800 In-Reply-To: <1454017365-8509-1-git-send-email-andi@firstfloor.org> References: <1454017365-8509-1-git-send-email-andi@firstfloor.org> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.10.4-0ubuntu2 Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, 2016-01-28 at 13:42 -0800, Andi Kleen wrote: > From: Andi Kleen > > The menu cpuidle governor does at least two int_sqrt() each time > we go into idle in get_typical_interval to compute stddev > > int_sqrts take 100-120 cycles each. Short idle latency is important > for many workloads. > > I instrumented the function on my workstation and most values are > 16bit only and most others 32bit (50% percentile is 122094, > 75% is 3699533). > > sqrt is implemented by starting with an initial estimation, > and then iterating. int_sqrt currently only uses a fixed > estimating which is good for 64bits worth of input. > > This patch adds some checks at the beginning to start with > a better estimate for values fitting in 8, 16bit and 32bit. > This makes int_sqrt between 60+% faster for values in 16bit, > and still somewhat faster (between 10 and 30%) for larger values > upto 32bit. Full 64bit is slightly slower. > > This optimizes the short idle calls and does not hurt the > long sleep (which probably do not care) much. > > An alternative would be a full table drive approach, or > trying some inverted sqrt optimization, but this simple change > already seems to have a good payoff. > > Signed-off-by: Andi Kleen > --- > lib/int_sqrt.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) > > diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c > index 1ef4cc3..2479ccf 100644 > --- a/lib/int_sqrt.c > +++ b/lib/int_sqrt.c > @@ -21,7 +21,15 @@ unsigned long int_sqrt(unsigned long x) > if (x <= 1) > return x; The above test (x <= 1) should also be moved > > - m = 1UL << (BITS_PER_LONG - 2); > + if (x <= 0xffff) { > + if (m <= 0xff) m or x ? if (x <= 0xff) looks more correct. > + m = 1UL << (8 - 2); > + else > + m = 1UL << (16 - 2); > + } else if (x <= 0xffffffff) > + m = 1UL << (32 - 2); > + else > + m = 1UL << (BITS_PER_LONG - 2); > while (m != 0) { > b = y + m; > y >>= 1;