您的位置:首页 > 运维架构

Mod of power 2 on bitwise operators?

2016-04-05 22:14 507 查看


Bitwise Alternatives to Multiply, Divide, and Modulus: Faster?

Aug 20, 2012

Tags: bitwise, divide, division, mod, modulus, multiplication, multiply, performance

Many programmers are aware of a special case where you can use a bitwise shift for multiplication or division when you’re multiplying or dividing by a power of two. For example, you can replace
i
* 2
with
i << 1
and
i
/ 2
with
i >> 1
. A lesser-known trick works for modulus. But are these alternatives actually any faster? Today's article
puts them to the test!

Here are today's competitors:

// Multiplication
i * 8; // normal
i << 3; // bitwise [8 = 2^3, so use 3]

// Division
i / 16; // normal
i >> 4; // bitwise [16 = 2^4, so use 4]

// Modulus
i % 4; // normal 2^2
i & 3; // bitwise [4 = 1 << 2, apply ((1 << 2) - 1), so use 3]

He meant that taking [code]number mod 2^n
is equivalent to stripping off all but the
n
lowest-order (right-most) bits of
number
.
[/code]
So in other words, [code]number mod 4
is the same as
number & 00000011
(where
&
means bitwise-and)
[/code]
What he means is that :[code]x modulo y = (x & (y − 1))
When y is a power of 2.

Here's a performance test that performs each of these operations a lot of times:

package
{
import flash.display.*;
import flash.utils.*;
import flash.text.*;

public class FasterDivMod extends Sprite
{
private var __logger:TextField = new TextField();
private function row(...cols): void
{
__logger.appendText(cols.join(",")+"\n");
}

public function FasterDivMod()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

__logger.autoSize = TextFieldAutoSize.LEFT;
addChild(__logger);

init();
}

private function init(): void
{
var beforeTime:int;
var afterTime:int;
var i:int;
var REPS:int = 100000000;
var absInt:int;

row("Method", "Time");

beforeTime = getTimer();
for (i = 0; i < REPS; ++i)
{
absInt = i / 4;
}
afterTime = getTimer();
row("Div: i / 4", (afterTime-beforeTime), absInt);

beforeTime = getTimer();
for (i = 0; i < REPS; ++i)
{
absInt = i >> 2;
}
afterTime = getTimer();
row("Div: i >> 2", (afterTime-beforeTime), absInt);

beforeTime = getTimer();
for (i = 0; i < REPS; ++i)
{
absInt = i * 4;
}
afterTime = getTimer();
row("Mul: i * 4", (afterTime-beforeTime), absInt);

beforeTime = getTimer();
for (i = 0; i < REPS; ++i)
{
absInt = i << 2;
}
afterTime = getTimer();
row("Mul: i << 2", (afterTime-beforeTime), absInt);

beforeTime = getTimer();
for (i = 0; i < REPS; ++i)
{
absInt = i % 4;
}
afterTime = getTimer();
row("Mod: i % 4", (afterTime-beforeTime), absInt);

beforeTime = getTimer();
for (i = 0; i < REPS; ++i)
{
absInt = i & 3; // ((1 << 2) - 1) == 3
}
afterTime = getTimer();
row("Mod: i & 3", (afterTime-beforeTime), absInt);
}
}
}

I ran this test app in the following environment:

Flex SDK (MXMLC) 4.6.0.23201, compiling in release mode (no debugging or verbose stack traces)
Release version of Flash Player 11.3.300.271
2.3 Ghz Intel Core i7
Mac OS X 10.8.0

And here are the results I got:
MethodTime
Div: i / 4358
Div: i >> 2224
Mul: i * 4206
Mul: i << 2255
Mod: i % 4918
Mod: i & 3254


The above results validate the bitwise versions in two out of three tests: division and modulus. In the multiplication case, the normal version actually performs about 20% faster than the bitwise equivalent. On the other hand, division is nearly twice as fast
with the bitwise shift and the bitwise modulus (really just an
&
) is more than three times faster! So if you're got a lot
of divides or mods in your performance-critical code, swap them over to the bitwise versions!

1) How does mod of power of 2 work on only lower order bits of a binary number (1011000111011010) ?
2) What is this number mod 2 to power 0, 2 to power 4 ?
3) What does power of 2 have to do with the modulo operator ? Does it hold a special property ?
4) Can someone give me an example ?

The instructor says "When you take something mod to power of 2 you just take its lower order bits". I was too afraid to ask what he meant =)

c math bit-manipulation bitwise-operators bitwise-and
shareimprove
this question
edited Oct
20 '15 at 11:44

asked Jul 12 '11 at 20:29





Zo Has
4,6301653118

3
Why don't you try a few example calculations by hand, then you'll see what happens. – starblue Jul
13 '11 at 10:20
add
a comment


5 Answers

activeoldestvotes

up vote22down
voteaccepted
He meant that taking
number
mod 2^n
is equivalent to stripping off all but the
n
lowest-order (right-most) bits
of
number
.

For example, if n == 2,
number      number mod 4
00000001      00000001
00000010      00000010
00000011      00000011
00000100      00000000
00000101      00000001
00000110      00000010
00000111      00000011
00001000      00000000
00001001      00000001
etc.


So in other words,
number
mod 4
is the same as
number
& 00000011
(where
&
means
bitwise-and)

Note that this works exactly the same in base-10:
number
mod 10
gives you the last digit of the number in base-10,
number
mod 100
gives you the last two digits, etc.

shareimprove
this answer
answered Jul 12 '11 at 20:40




BlueRaja - Danny Pflughoeft
42.8k18111186

Thank you so much. – Zo
Has Jul
12 '11 at 21:08
add
a comment


up vote9down
vote
What he means is that :
x modulo y = (x & (y − 1))


When y is a power of 2.

Example:
0110010110 (406) modulo
0001000000 (64)  =
0000010110 (22)
^^^^<- ignore these bits


Using your example now :
1011000111011010 (45530) modulo
0000000000000001 (2 power 0) =
0000000000000000 (0)
^^^^^^^^^^^^^^^^<- ignore these bits

1011000111011010 (45530) modulo
0000000000010000 (2 power 4) =
0000000000001010 (10)
^^^^^^^^^^^^<- ignore these bits


shareimprove
this answer
edited Jul
12 '11 at 20:40

answered Jul 12 '11 at 20:34





Veronika Prüssels
25.1k44883

Hey thanks for the reply. I did not got your example completely ? – Zo
Has Jul
12 '11 at 20:36
add
a comment
up vote6down
vote
Consider when you take a number modulo 10. If you do that, you just get the last digit of the number.
334 % 10 = 4
12345 % 10 = 5


Likewise if you take a number modulo 100, you just get the last two digits.
334 % 100 = 34
12345 % 100 = 45


So you can get the modulo of a power of two by looking at its last digits in binary. That's the same as doing a bitwise and.

shareimprove
this answer
answered Jul 12 '11 at 20:35





Brian
1,231819

Would that hold for powers of 2 as well ? 54 % 32 which is 2^5 gives 22. – Zo
Has Jul
12 '11 at 21:07
Popo: Yes. The number of bits at the end is determined by which power of two you're using. As described by Cicada, you
would calculate it as 54 & (32-1). – Brian Jul
12 '11 at 21:39
add
a comment
up vote3down
vote
Modulo in general returns the remainder of a value after division. So
x
mod 4
, for example, returns 0, 1, 2 or 3 depending on x. These possible values can be represented using two bits in binary (00, 01, 10, 11) - another way to do
x
mod 4
is to simply set all the bits to zero in x except the last two ones.

Example:
x = 10101010110101110
x mod 4 = 00000000000000010


shareimprove
this answer
answered Jul 12 '11 at 20:38





Antti
5,64811322

add
a comment
up vote2down
vote
Answering your specific questions:

mod is a remainder operator. If applied to a series of numbers x in 0, 1, ..., then x mod n will be 0, 1, ..., n-1, 0, 1, ..., n-1, ad infinitum. When your modulus n is a power
of 2, then x mod n will count up in binary from 0 to n-1, back to 0, to n-1, etc; for modulus n that looks like binary 01xxxxx, x mod n will cycle through every of those low-order bits xxxxx.
binary 1011000111011010 mod 1 is 0 (mod 2^0 yields the last zero bits; everything mod 1 is zero). binary 1011000111011010 mod binary 10000 is 1010 (mod 2^4 yields the last four
bits).
Division and remainder of binary number by powers of two is particularly efficient because it's just shifting and masking; mathematically it's nothing special.
Example: See answer to question 2.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: