]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
util: Add ALIGN_POWER2
authorLucas De Marchi <lucas.demarchi@intel.com>
Thu, 22 Aug 2013 04:10:13 +0000 (01:10 -0300)
committerLucas De Marchi <lucas.demarchi@intel.com>
Fri, 20 Sep 2013 06:08:46 +0000 (01:08 -0500)
Add static inline function to align a value to it's next power of 2.
This is commonly done by a SWAR like the one in:

http://aggregate.org/MAGIC/#Next Largest Power of 2

However a microbench shows that the implementation herer is a faster.
It doesn't really impact the possible user of this function, but it's
interesting nonetheless.

Using a x86_64 i7 Ivy Bridge it shows a ~4% advantage by using clz
instead instead of the OR and SHL chain. And this is by using a BSR
since Ivy Bridge doesn't have LZCNT. New Haswell processors have the
LZCNT instruction which can make this even better. ARM also has a CLZ
instruction so it should be better, too.

Code used to test:

...
v = val[i];
t1 = get_cycles(0);
a = ALIGN_POWER2(v);
t1 = get_cycles(t1);

t2 = get_cycles(0);
v = nlpo2(v);
t2 = get_cycles(t2);

printf("%u\t%llu\t%llu\t%d\n", v, t1, t2, v == a);
...

In which val is an array of 20 random unsigned int, nlop2 is the SWAR
implementation and get_cycles uses RDTSC to measure the performance.

Averages:
ALIGN_POWER2:  30 cycles
nlop2: 31.4 cycles

libkmod/libkmod-util.h

index f7f3e90d9290d5ab2e254f1fec74944102841133..8a70aebf66694dcfb3d5cfbf146e3dd75176ed52 100644 (file)
@@ -51,3 +51,8 @@ do {                                          \
        } *__p = (typeof(__p)) (ptr);           \
        __p->__v = (val);                       \
 } while(0)
+
+static _always_inline_ unsigned int ALIGN_POWER2(unsigned int u)
+{
+       return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
+}