Help - How to get the most significant bit

Started by
32 comments, last by zeelot 18 years, 9 months ago
Quote:Original post by FlowingOoze
Quote:Original post by Nice Coder
Yep. Assuming a comparison ain't that expencive, its one of the best options.

The best option is a lut assisted binary search.

My best would be only a few comparisons. (ie. somewhere near three), and a 256 element lut.

Assume you have a 32 bit number.

First you test the first 16 bits. (jz, no cmp needed. Use the 16 bit registers)
Then if its true, then you try the first 8 bits. (another jz).
If that doesn't work, then you just use the lut on the output.

If the first 16 bits are false, then you just try the other way. (same thing, just using different registers).

i'm pretty sure an optimised asm version would be superfast.

From,
Nice coder

ARM doesn't have 16-bit subregisters. Other than that, this approach is worth trying and does actually return the MSB bit number. However one should not forget the penalty incurring from a cache miss when accessing the lut.
Though I still don't understand why anyone would need something like this when a three instruction loop does the trick in no more that 32 iterations.



Neither do i. But its a nice problem.

Also 3 instructino loop (+ overhead, your've got two instructions loop overhad, with branch mispredictions, ect. with another 4-5 in the loop itself.)

Assume you've got 7 instructions in the main loop.
7*31 = 217 instructions.
Thats pretty big. (tho nothing major unless your doing it heaps)

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
Advertisement
Quote:Original post by Nice Coder
My method can find it in o(log2(log2(n)) where n is the biggest number that you want it to use.

That's 5+1 operations vs. average of 16 for 32-bit numbers. In other words, it's only worth the extra lines of code if it's really performance critical. Still, it's a nice trick to remember, if ever needed.
Quote:Original post by zeelot
We need to know WHICH bit is its MSB (Most Significant Bit).
There are gazillion ways of doing this. Here is one:

int ilog2(unsigned int i) {    int b = 0;    if ((i & 0xAAAAAAAA) > (i & 0x55555555)) b++;    if ((i & 0xCCCCCCCC) > (i & 0x33333333)) b += 2;    if ((i & 0xF0F0F0F0) > (i & 0x0f0f0f0f)) b += 4;    if ((i & 0xFF00FF00) > (i & 0x00ff00ff)) b += 8;    if ((i & 0xFFFF0000) > 0) b += 16;    return b;}


Here's another one:

int ilog2(unsigned int i) {    int b = 0;    if (i & 0xffff0000) b += 16; else i<<=16;    if (i & 0xff000000) b += 8; else i<<=8;    if (i & 0xf0000000) b += 4; else i<<=4;    if (i & 0xc0000000) b += 2; else i<<=2;    if (i & 0x80000000) b += 1;    return b;}

Quote:Original post by Nice Coder

Also 3 instructino loop (+ overhead, your've got two instructions loop overhad, with branch mispredictions, ect. with another 4-5 in the loop itself.)

Assume you've got 7 instructions in the main loop.
7*31 = 217 instructions.
Thats pretty big. (tho nothing major unless your doing it heaps)

From,
Nice coder


I can't be bothered to lookup ARM instruction set right now, but I think you can do the entire loop in three:

1. Increment MSB bit counter
2. Shift left and set flags
3. Branch if not zero

So it's only 3*31 = 93 instructions and if all integers are equally likely, it's half of that on average, ie. 41.5 . If the MSB is more likely to be small, then it's faster than 41.5 on average. If it's more likely to be bigger, then the loop can be written to shift in the other direction and again get a better average.

I don't know how different ARM processor do branch prediction, but the branch is always taken, except on the last iteration, so it has a pretty good change of getting it right.


[Edited by - FlowingOoze on July 11, 2005 3:02:34 AM]
Quote:Original post by Christer Ericson
Quote:Original post by zeelot
We need to know WHICH bit is its MSB (Most Significant Bit).
There are gazillion ways of doing this. Here is one:

*** Source Snippet Removed ***

Here's another one:

*** Source Snippet Removed ***

This is the binary search that was mentioned. Roughly counting the instructions needed, for the latter: 19, of which five are branches, with 50% change of correct branch prediction. I'm inclined to think that this is somewhat faster than a loop.

EDIT: Actually on second though, one could write this using conditional codes in instructions and avoid branch misprediction. I'd say this is much faster, if optimised properly.


[Edited by - FlowingOoze on July 11, 2005 3:13:19 AM]
Quote:Original post by Christer Ericson
Quote:Original post by zeelot
We need to know WHICH bit is its MSB (Most Significant Bit).
There are gazillion ways of doing this. Here is one:

*** Source Snippet Removed ***

Here's another one:

*** Source Snippet Removed ***


Did you write some chunky to planar converters in the old days? :) Those masks bring back old memories...
Praise the alternative.
Quote:Original post by FlowingOoze
I can't be bothered to lookup ARM instruction set right now, but I think you can do the entire loop in three:

1. Increment MSB bit counter
2. Shift left and set flags
3. Branch if not zero

So it's only 3*31 = 93 instructions and if all integers are equally likely, it's half of that on average, ie. 41.5 . If the MSB is more likely to be small, then it's faster than 41.5 on average. If it's more likely to be bigger, then the loop can be written to shift in the other direction and again get a better average.

I don't know how different ARM processor do branch prediction, but the branch is always taken, except on the last iteration, so it has a pretty good change of getting it right.


Unfortunatly that doesn't work.

Exersise to the reader to find out why.

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
Quote:Original post by Christer Ericson
Quote:Original post by zeelot
We need to know WHICH bit is its MSB (Most Significant Bit).
There are gazillion ways of doing this. Here is one:

*** Source Snippet Removed ***

Here's another one:

*** Source Snippet Removed ***


I am sorry, but this opinion must be said.

OMG THAT IS SO 1337!!!

And also, Rate++.

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
Quote:Original post by Nice Coder
Unfortunatly that doesn't work.

Exersise to the reader to find out why.

From,
Nice coder


what are you talking about? What he said was basicly that
int MSB(unsigned x){	int n = 0;	for(; x >>= 1; ++n);	return n;}

probably can be implemented using very few instructions, I've never seen arm ASM but his guesstimate on three instructions sounds about right.

It's still not very efficent but it's about as simple as can be.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
I don't know about the ARM processor, but on x86 processors there is the BSR instruction to do this.

This topic is closed to new replies.

Advertisement