LISTS: Extract every other element

Christian Tismer tismer at appliedbiometrics.com
Mon Dec 20 13:19:24 EST 1999


Randall Hopper wrote:
> 
>    eric jones:
>    Mike Fletcher:
>       |>>> from Numeric import *
>       |>>> a = array(range(10))
>       |>>> a[::2]
> 
> Pretty fast.
> 
>    Christian Tismer:
>       |def slice100(d):
> 
> Most impressive.  Not as readable, but amazing performance without having
> to resort to a C extension.

Your results are most interesting. Mike did the Numeric tests
without re-converting to a true list. You do it, and then
I beat Numeric. This was what I expected, btw.

I also assume that you do one test after the other, many times?
If not, I loose! :-))
This is since I use an unusual stack size which causes
reallocs of stack frames, which in turn causes reallocs
of result variables which no longer fit the hole.

I'm working on a malloc scheme for Python which does not
suffer from this. Mallocs will be cahced with the code
location.

> APPROACH #8  |   33.29%  (0.696691 sec)    |      34.40%  (0.686397 sec) *
> APPROACH #9  |   31.34%  (0.656048 sec)    |      34.14%  (0.681241 sec)

> APPROACH #8  - Christian's 100 element walker
> APPROACH #9  - lst2 = mxTools.extract( lst, mxTools.trange( 0, len(lst), 2 ) )

This is unbelievable. Marc has the extra overhead of creating the
trange object, I have the overhead of the three interpreted
machine instructions.
But we are both stopped by the C API, which always goes through
the general object protocol. Let's see how fast we can get:

try:
	from slice2 import everyother
except:
	everyother = None

if everyother:
	data = range(1000000)
	print timing(chrisInline, data, 10)[0]
	print timing(everyother, data, 10)[0]

25.54
3.02	

This tells us that we can be 8 times faster. :-)

Here your module:


-------- slice2.c --------
/* very quick hack for randall Hopper
	to show how fast slicing can be,
	and to give him a fast module
	with thanks for the nice race

  Chris Tismer, 991220
*/

/* start: 6:40 pm */

#include "python.h"

PyObject *
everyother(self, args)
	PyObject *self, *args;
{
	PyObject *inlist, *outlist, *thing;
	int p, p2;
	int insize, outsize;
	if (PyTuple_GET_SIZE(args) != 1
		|| !(PyList_Check(PyTuple_GET_ITEM(args, 0))) ) {
		PyErr_SetString(PyExc_TypeError, 
			"everyother needs exactly one list argument");
		return NULL;
	}
	inlist = PyTuple_GET_ITEM(args, 0);
	insize = PyList_GET_SIZE(inlist);
	outsize = insize / 2;
	outlist = PyList_New(outsize);
	if (!outlist)
		/* must be mem error */
		return NULL;
	for ( p=1, p2=0 ; p2 < outsize ; p+=2, p2++) {
		thing = PyList_GET_ITEM(inlist, p);
		Py_INCREF(thing);
		PyList_SET_ITEM(outlist, p2, thing);
	}
	return outlist;
}

static PyMethodDef slice2_methods[] = {
  {"everyother",	(PyCFunction)everyother, 1},
  {NULL,		NULL}		/* sentinel */
};

#ifdef _MSC_VER
_declspec(dllexport)
#endif
void
initslice2()
{
	PyObject *m;

	m = Py_InitModule("slice2", slice2_methods);
}

/* finished 7:00 pm */

/* finished testing & debugging: 7:20 pm */

------ end of slice2.c -------

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer at appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaiserin-Augusta-Allee 101   :    *Starship* http://starship.python.net
10553 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     we're tired of banana software - shipped green, ripens at home




More information about the Python-list mailing list