What is the most efficient algorithm to achieve the following:
0010 0000 => 0000 0100
The conversion is from MSB->LSB to LSB->MSB. All bits must be reversed; that is, this is not endianness-swapping.
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
NOTE: All algorithms below are in C, but should be portable to your language of choice (just don’t look at me when they’re not as fast 🙂
Options
Low Memory (32-bit
int, 32-bit machine)(from here):From the famous Bit Twiddling Hacks page:
Fastest (lookup table):
You can extend this idea to 64-bit
ints, or trade off memory for speed (assuming your L1 Data Cache is large enough), and reverse 16 bits at a time with a 64K-entry lookup table.Others
Simple
Faster (32-bit processor)
Faster (64-bit processor)
If you want to do this on a 32-bit
int, just reverse the bits in each byte, and reverse the order of the bytes. That is:Results
I benchmarked the two most promising solutions, the lookup table, and bitwise-AND (the first one). The test machine is a laptop w/ 4GB of DDR2-800 and a Core 2 Duo T7500 @ 2.4GHz, 4MB L2 Cache; YMMV. I used gcc 4.3.2 on 64-bit Linux. OpenMP (and the GCC bindings) were used for high-resolution timers.
reverse.c
reverse_lookup.c
I tried both approaches at several different optimizations, ran 3 trials at each level, and each trial reversed 100 million random
unsigned ints. For the lookup table option, I tried both schemes (options 1 and 2) given on the bitwise hacks page. Results are shown below.Bitwise AND
Lookup Table (option 1)
Lookup Table (option 2)
Conclusion
Use the lookup table, with option 1 (byte addressing is unsurprisingly slow) if you’re concerned about performance. If you need to squeeze every last byte of memory out of your system (and you might, if you care about the performance of bit reversal), the optimized versions of the bitwise-AND approach aren’t too shabby either.
Caveat
Yes, I know the benchmark code is a complete hack. Suggestions on how to improve it are more than welcome. Things I know about:
ldblew up with some crazy symbol redefinition error), so I don’t believe the generated code is tuned for my microarchitecture.32-bit
EDIT: I also tried using
uint64_ttypes on my machine to see if there was any performance boost. Performance was about 10% faster than 32-bit, and was nearly identical whether you were just using 64-bit types to reverse bits on two 32-bitinttypes at a time, or whether you were actually reversing bits in half as many 64-bit values. The assembly code is shown below (for the former case, reversing bits for two 32-bitinttypes at a time):