Shifting a double-wide variable - bit twiddling

  • Thread starter Thread starter CRGreathouse
  • Start date Start date
  • Tags Tags
    Bit Variable
Click For Summary
SUMMARY

The discussion focuses on optimizing the shifting of a double-wide variable, specifically using two unsigned long long variables, left and right, to handle values exceeding 64 bits. The proposed method involves a right shift of 2 bits, utilizing bitwise operations to minimize execution time. Key suggestions include replacing addition with bitwise OR for combining bits and reducing operations by eliminating redundant bit masking. The conversation emphasizes the importance of compile-time shift sizes and considers the efficiency of shifts on modern processors.

PREREQUISITES
  • Understanding of unsigned long long data type
  • Familiarity with bitwise operations (AND, OR, shifts)
  • Knowledge of processor architecture and performance characteristics
  • Experience with C or C++ programming languages
NEXT STEPS
  • Research compiler optimizations for bit manipulation in C/C++
  • Learn about modern CPU architectures and their handling of bit shifts
  • Explore advanced bit twiddling techniques for performance enhancement
  • Investigate the impact of branch misprediction on performance in low-level programming
USEFUL FOR

Software developers, particularly those working on performance-critical applications, systems programmers, and anyone interested in low-level bit manipulation techniques.

CRGreathouse
Science Advisor
Homework Helper
Messages
2,832
Reaction score
0
Shifting a double-wide variable -- bit twiddling

I have a number too long to fit into the largest variable size (unsigned long long, 64 bits in this case) so I'm storing it in two variables, left and right. I want to shift it -- and to do it quickly, as I'll do this more than 1e12 times.

The 'obvious' way is

Code:
unsigned long long right, left;

. . .

right = ((left&3) << 62) + (right >> 2);
left >>= 2;

for a total of 5 operations and two assignments. This example is a right shift of 2, but right shifts by 1 and 4 are also important. In any case the size of the shift should be known at compile time.

1. Is a shift of 62 too large to be done efficiently? I know that older processors used to take O(n) time to shift n places (something like 3+n micro-ops), but I don't know if this holds on modern processors. Perhaps I should make a switch statement with constant to add (1 << 62, 2 << 62, and 3 << 62 precomputed)? Or would the branch misprediction outweigh this?
2. Is there a way to do this with fewer operations? I'm sure there are some people out there who have been doing bit manipulations far longer than I have.

For what it's worth I'm on a Core Duo, but I'm hoping for improvements to my program that work on most systems.
 
Technology news on Phys.org
You can replace "(left&3)" with just "left" since the bit mask operation is redundant given the left shift. It cuts your cost down to 4 operations.

I would also replace the "+" operator with a bitwise OR instead. You are not adding values but combining bits. It may not actually save any execution time, but a "|" is simpler than a "+" operation so there is a remote chance that it is faster on some systems.

right >>= 2;
right |= left << 62;
left >>= 2;
 
Ooh, thanks. That does help.
 

Similar threads

  • · Replies 17 ·
Replies
17
Views
4K
  • · Replies 19 ·
Replies
19
Views
2K
  • · Replies 10 ·
Replies
10
Views
4K
  • · Replies 7 ·
Replies
7
Views
4K
  • · Replies 15 ·
Replies
15
Views
3K
Replies
4
Views
2K
  • · Replies 25 ·
Replies
25
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K