| leonardo ( @ 2009-02-03 14:56:00 |
| Entry tags: | benchmark, java, programming, python |
Multiprecision integers
Built-in Python multiprecision integers (long) are handy but they aren't know for their speed. If you want speed you usually go with GMPY (http://gmpy.sourceforge.net/ ). I was curious to see how much slower are such numbers compared to the BigInteger of a common JavaVM.
So I have compared the multiplication efficienty (I think mutiplications aren't done much efficiently in Python long) with a basic program:
// Java code
import java.math.BigInteger;
public class Fact {
public static void main() {
BigInteger n = BigInteger.ONE;
for (int i = 1; i <= 20000; i++)
n = n.multiply(BigInteger.valueOf(i));
}
}
// Python code #1
def main():
n = 1
for i in xrange(1, 20000+1):
n *= i
main()
// Python code #2
from gmpy import mpz
def main():
n = mpz(1)
for i in xrange(1, 20000+1):
n *= i
main()
// Python code #3
from gmpy import mpz
import psyco
def main():
n = mpz(1)
for i in xrange(1, 20000+1):
n *= i
psyco.bind(main)
main()
// Python code #4
from gmpy import fac
fac(20000)
// D + Tango
import tango.math.BigInt: BigInt;
void main() {
BigInt n = "1";
for (int i = 1; i <= 20_000; i++)
n *= i;
}
Timings:
Java: 15.59 s
Python1: 4.51 s
D: 4.20 s
Python2: 1.66 s
Python3: 1.23 s
Python4: 0.31 s
Notes on the D code:
- At the end the number 'n' is represented in 32116 bytes.
- I'd like to initialize n with a normal integral value, and not a string: BigInt n = 1;
- To print n you have to use (on Tango) something like: Cout(n.toDecimalString).newline; this is ugl, it needs a toString() for simple purposes (plus other things for more complex purposes).
CPU used: Pentium III 500 MHz.
VM/compiler/libs used:
- Python 2.5.2
- GMPY V.1.02
- java version "1.6.0_10"
- LDC D compiler with V.0.9 (rev 877) based on DMD v1.039 and llvm 2.4, with Tango.
The results of Python1 vs Java have surprised me, is someone able to explain them?