I help maintain the gmpy library and I've been experimenting with a
Cython-based wrapper for GMP. I've done simple performance tests with
an early version of the library and it is slower than the C-based gmpy
library. I compared object creation and addition times for Python
longs, gmpy, and gmpy3 (the experimental library). These are my
results, in seconds (code is below):
create times
long: 2.25385284424
gmpy: 1.70728683472
gmpy3: 2.3947558403
addition times
long: 3.03700900078
gmpy: 2.6448340416
gmpy3: 4.70184206963
Do you have any suggestions for improving the performance?
Thanks,
Case
--------------------------------------------
The test script:
import time
import gmpy
import gmpy3
def create_test(ctor, times):
start = time.time()
for i in range(times):
a=ctor(i)
return (time.time() - start)
def addition_test(ctor, times):
b = ctor('12345678901234567890')
start = time.time()
for i in range(times):
a=ctor(i) + b
return (time.time() - start)
print "create times"
print "long: ", create_test(long, 10000000)
print "gmpy: ", create_test(gmpy.mpz, 10000000)
print "gmpy3: ", create_test(gmpy3.mpz, 10000000)
print
print "addition times"
print "long: ", addition_test(long, 10000000)
print "gmpy: ", addition_test(gmpy.mpz, 10000000)
print "gmpy3: ", addition_test(gmpy3.mpz, 10000000)
-----------------------------------------------------------------
Excerpts from gmpy3.pyx
cdef class mpz:
"""
Wrapper for GMP multiple-precision integers.
"""
cdef mpz_t z
def __init__(self, val=None, base=10):
"""
Initialize a variable of type mpz.
"""
cdef _longobject *l
if val is None:
mpz_init(self.z)
elif PyInt_CheckExact(val):
mpz_init_set_si(self.z, val)
elif PyString_CheckExact(val):
if mpz_init_set_str(self.z, val, base):
raise ValueError('Invalid literal for mpz() with base
' + str(base))
elif PyLong_CheckExact(val):
mpz_init(self.z)
l = <_longobject *> val
if l.ob_size < 0:
negval = True
length = - l.ob_size
else:
negval = False
length = l.ob_size
mpz_import(self.z, length, -1, sizeof(l.ob_digit[0]), 0,
sizeof(l.ob_digit[0])*8 - SHIFT, l.ob_digit)
if negval:
mpz_neg(self.z, self.z)
elif PyFloat_CheckExact(val):
mpz_init_set_d(self.z, val)
elif isinstance(val, mpz):
mpz_init_set(self.z, (<mpz>val).z)
else:
raise TypeError('mpz() argument must be string, int, long,
or float')
def __dealloc__(self):
mpz_clear(self.z)
def __add__(self, other):
cdef int temp
result = mpz()
cdef mpz Z
if isinstance(self, mpz):
if isinstance(other, mpz):
mpz_add((<mpz>result).z, (<mpz>self).z, (<mpz>other).z)
elif PyInt_CheckExact(other):
if other >= 0:
mpz_add_ui((<mpz>result).z, (<mpz>self).z, other)
else:
mpz_sub_ui((<mpz>result).z, (<mpz>self).z, abs(other))
else:
mpz_add((<mpz>result).z, (<mpz>self).z, (<mpz>mpz(other)).z)
return result
else:
return mpz.__add__(other, self)
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev