Hi Jim,
It depends a lot on what you're doing. You will get speed up from Pyrex
or wrapping C code if you understand how does it work internally, and to
speed up you application via coding *only* Pyrex parts (I mean don't
using it for wrapping C but implementing in Pyrex), it limits a lot the
things that you can expect to get faster -'cause on some kind of things
you can even get better performance coding that in straight Python than
in Pyrex and converted to C & compiled, I thought you should know how
Python works in the C side to understand it fully-.
I attach some examples of different code where C is a lot faster, or
just a little bit faster (and I compare with C counterparts, not Pyrex
ones -Pyrex is only used for wrapping in these examples-). So you can
get an idea of why depends a lot on what you're doing. If you plan only
using cdefs to speed-up Python code, you're very limited in the things
that could be speed-up. Try to do some experiments and examine the C
generated code by Pyrex, and you will see why it is -you will see how
Pyrex does Python C api function calls for conversion from Python
objects to C type values every time you use that var, and that's not a
great gain, even in some kind of operations can be worse as Python does
a better job than generated C code by Pyrex for some operations or value
conversions (i.e. when doing operations on some kind of iterable objects
I remember to read on some paper that Pyrex does not traslate to the
faster C approach)
Some days ago I posted some timing results for a function coded in
Python, or coded in C and wrapped by Pyrex. C approach was more than 80
times faster. And I attach below another one, where C isn't much a gain
(1 time faster).
Example A:
This code is more than 80 times faster than a "easy" Python
implementation. For every call, it does some bitwise operations and does
an array lookup for every string character from argument. Its a lot
faster because in Python approach a list lookup is done and it is a lot
faster to do a C array lookup -thought that in these C loops no Python
type value conversions are needed, if it where the case, C approach
would not be so faster than python. I don't know how would perform an
array based Python code, but I expect it to be a lot faster than using a
list, so Python code can be speed up a lot if you know how to do it.
// C code:
int CRC16Table[256]; // Filled elsewhere
int CalcCRC16(char *str)
{
int crc;
for(crc = 0xFFFF; *str != 0; str++) {
crc = CRC16Table [(( crc >> 8 ) & 255 )] ^ ( crc << 8 ) ^ *str;
}
return crc;
}
# Python code
gCRC16Table = [] # Filled elsewhere
def CalcCRC16(astr):
crc = 0xFFFFL
for c in astr:
crc = gCRC16Table[((crc >> 8) & 255)] ^ ((crc & 0xFFFFFF) << 8)
^ ord(c)
return crc
-------------------------------------------------------------------------
Example B:
If we do compare the functions below, Python approach is only a bit
slowly than C implementation. I know both aren't the faster approaches
for every language, but that's a different issue. C here is only about 1
time faster:
// C code. gTS type is struct { int m, int s }
gTS gTS_diff(gTS t0, gTS t1) {
gTS retval;
retval.s = (t1.s-t0.s);
if ((t0.m>t1.m)) {
retval.m = (t1.m-t0.m);
while((retval.m<0)) {
retval.s = (retval.s-1);
retval.m = (m+1000);
}
} else {
retval.m = (t1.m-t0.m);
}
while((retval.m>999)) {
retval.m = (retval.m-1000);
retval.s = (retval.s+1);
}
return retval;
}
# Python code (t0 and t1 are tuples)
def gts_diff(t0,t1):
s = t1[0] - t0[0]
if (t0[1] > t1[1]):
m = t1[1] - t0[1]
while m < 0:
s = s - 1
m = m + 1000
else:
m = t1[1] - t0[1]
while m > 999:
m = m - 1000
s = s + 1
return s, m
I encourage you to google for some Pyrex papers on the net, they explain
the "to do"'s and the "not to do"'s with Pyrex. Sorry but I don't have
the urls.
Regards,
Gonzalo
Jim Lewis escribió:
I never had an opportunity to do any more sophisticated math than simple adding,
multiplying, subtracting and dividing.
Neither is the primes example doing anything more sophisticated than
basic arithmetic but it's 50 times faster.