Quantcast
Viewing latest article 25
Browse Latest Browse All 36

Answer by Josh for What is the fastest/most efficient way to find the highest set bit (msb) in an integer in C?

Here are some (simple) benchmarks, of algorithms currently given on this page...

The algorithms have not been tested over all inputs of unsigned int; so check that first, before blindly using something ;)

On my machine clz (__builtin_clz) and asm work best. asm seems even faster then clz... but it might be due to the simple benchmark...

//////// go.c ///////////////////////////////// compile with:  gcc go.c -o go -lm#include <math.h>#include <stdio.h>#include <stdlib.h>#include <time.h>/***************** math ********************/#define POS_OF_HIGHESTBITmath(a) /* 0th position is the Least-Signif-Bit */    \  ((unsigned) log2(a))         /* thus: do not use if a <= 0 */  #define NUM_OF_HIGHESTBITmath(a) ((a)               \                  ? (1U << POS_OF_HIGHESTBITmath(a))    \                  : 0)/***************** clz ********************/unsigned NUM_BITS_U = ((sizeof(unsigned) << 3) - 1);#define POS_OF_HIGHESTBITclz(a) (NUM_BITS_U - __builtin_clz(a)) /* only works for a != 0 */#define NUM_OF_HIGHESTBITclz(a) ((a)                    \                 ? (1U << POS_OF_HIGHESTBITclz(a))  \                 : 0)/***************** i2f ********************/double FF;#define POS_OF_HIGHESTBITi2f(a) (FF = (double)(ui|1), ((*(1+(unsigned*)&FF))>>20)-1023)#define NUM_OF_HIGHESTBITi2f(a) ((a)                    \                 ? (1U << POS_OF_HIGHESTBITi2f(a))  \                 : 0)/***************** asm ********************/unsigned OUT;#define POS_OF_HIGHESTBITasm(a) (({asm("bsrl %1,%0" : "=r"(OUT) : "r"(a));}), OUT)#define NUM_OF_HIGHESTBITasm(a) ((a)                    \                 ? (1U << POS_OF_HIGHESTBITasm(a))  \                 : 0)/***************** bitshift1 ********************/#define NUM_OF_HIGHESTBITbitshift1(a) (({   \  OUT = a;                  \  OUT |= (OUT >> 1);                \  OUT |= (OUT >> 2);                \  OUT |= (OUT >> 4);                \  OUT |= (OUT >> 8);                \  OUT |= (OUT >> 16);               \      }), (OUT & ~(OUT >> 1)))          \/***************** bitshift2 ********************/int POS[32] = {0, 1, 28, 2, 29, 14, 24, 3,             30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19,             16, 7, 26, 12, 18, 6, 11, 5, 10, 9};#define POS_OF_HIGHESTBITbitshift2(a) (({   \  OUT = a;                  \  OUT |= OUT >> 1;              \  OUT |= OUT >> 2;              \  OUT |= OUT >> 4;              \  OUT |= OUT >> 8;              \  OUT |= OUT >> 16;             \  OUT = (OUT >> 1) + 1;             \      }), POS[(OUT * 0x077CB531UL) >> 27])#define NUM_OF_HIGHESTBITbitshift2(a) ((a)              \                       ? (1U << POS_OF_HIGHESTBITbitshift2(a)) \                       : 0)#define LOOPS 100000000Uint main(){  time_t start, end;  unsigned ui;  unsigned n;  /********* Checking the first few unsigned values (you'll need to check all if you want to use an algorithm here) **************/  printf("math\n");  for (ui = 0U; ui < 18; ++ui)    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITmath(ui));  printf("\n\n");  printf("clz\n");  for (ui = 0U; ui < 18U; ++ui)    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITclz(ui));  printf("\n\n");  printf("i2f\n");  for (ui = 0U; ui < 18U; ++ui)    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITi2f(ui));  printf("\n\n");  printf("asm\n");  for (ui = 0U; ui < 18U; ++ui) {    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITasm(ui));  }  printf("\n\n");  printf("bitshift1\n");  for (ui = 0U; ui < 18U; ++ui) {    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITbitshift1(ui));  }  printf("\n\n");  printf("bitshift2\n");  for (ui = 0U; ui < 18U; ++ui) {    printf("%i\t%i\n", ui, NUM_OF_HIGHESTBITbitshift2(ui));  }  printf("\n\nPlease wait...\n\n");  /************************* Simple clock() benchmark ******************/  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITmath(ui);  end = clock();  printf("math:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITclz(ui);  end = clock();  printf("clz:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITi2f(ui);  end = clock();  printf("i2f:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITasm(ui);  end = clock();  printf("asm:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITbitshift1(ui);  end = clock();  printf("bitshift1:\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  start = clock();  for (ui = 0; ui < LOOPS; ++ui)    n = NUM_OF_HIGHESTBITbitshift2(ui);  end = clock();  printf("bitshift2\t%e\n", (double)(end-start)/CLOCKS_PER_SEC);  printf("\nThe lower, the better. Take note that a negative exponent is good! ;)\n");  return EXIT_SUCCESS;}

Viewing latest article 25
Browse Latest Browse All 36

Trending Articles