Psycho question

David C. Ullrich dullrich at sprynet.com
Thu Aug 7 14:20:35 EDT 2008


In article 
<de4e128d-537e-42cd-8706-f2c7f0f3931f at p25g2000hsf.googlegroups.com>,
 MRAB <google at mrabarnett.plus.com> wrote:

> On Aug 6, 8:52 pm, "David C. Ullrich" <dullr... at sprynet.com> wrote:
> > In article
> > <8f0dc2a7-d3bd-4632-a282-9428c9100... at e53g2000hsa.googlegroups.com>,
> >
> >  bearophileH... at lycos.com wrote:
> > > David C. Ullrich:
> > > > Thanks. If I can get it installed and it works as advertised
> > > > this means I can finally (eventually) finish the process of
> > > > dumping MS Windows: the only reason I need it right now is for
> > > > the small number of Delphi programs I have for which straight
> > > > Python is really not adequate. Been not looking forward to
> > > > learning some C or Objective C (or whatever that Mac thing
> > > > is) - if I can just "accelerate" a few Python routines that'll
> > > > be great.
> >
> > > To have better performance with Psyco you need low-level style code,
> > > generally not lazy, etc, and adopt some programming conventions, so
> > > you may have to rewrite your routines for max speed.
> >
> > Thanks. I would have guessed that I'd want low-level style code;
> > that's the sort of thing I have in mind. In fact the only thing
> > that seems likely to come up right now is looping through an
> > array of bytes, modifying them. The plan is to use the array
> > module first to convert a string or a list to an array, outside
> > the accelerated part, then maybe do something like
> >
> > for j in range(len(bytes)/3):
> >   g = (bytes[3*j] + bytes[3*j+1] + bytes[3*j+2])/3
> >   bytes[3*j] = bytes[3*j+1] = bytes[3*j+2] = g
> >
> > then convert back to a list or string or whatever outside
> > the accelerated function.
> >
> [snip]
> A couple of points:
> 
> 1. '/' with ints in Python 2.x returns an int, but from Python 3.x
> it'll return a float. You're recommended to use '//' for int division.
> 
> 2. 'range' can accept a step value, so you can rewrite that as:
> 
>     for j in range(0, len(bytes), 3):
>         g = (bytes[j] + bytes[j+1] + bytes[j+2])//3 # I think you also
> want // here
>         bytes[j] = bytes[j+1] = bytes[j+2] = g

Not the issues I expected to be worrying about here, but thanks.

Of course the range(0, len(bytes), 3) is more elegant, and
it's probably faster in Python, but curiously it's much
slower under Psyco! Otoh xrange(0, len(bytes), 3) becomes
pretty fast again. So I conjecture that Psyco compiles
"for j in range(l)" just as a loop but actually constructs
an array for range(0, l, step).

Also very curiously, // inside the loop is much slower than
/ here (under Psyco). This one I'm not going to guess why...

Honest:

"""Ah - psyco does work with exec if the import psyco,
etc is inside the code being executed (right now it's
in its own namespace, hence a fresh import each time 
- check whether this works with exec in default
namespaces).

Ie, this script works fine in DUShell:"""

from psyco import proxy, bind

def f(b):
  for j in range(len(b)/3):
    i = 3*j
    g = (b[i] + b[i+1] + b[i+2])/3
    b[i] = b[i+1] = b[i+2] = g

g = proxy(f)

def h(b):
  for j in range(0,len(b),3):
  #for i in range(len(b)/3):
    #j = 3*i
    g = (b[j] + b[j+1] + b[j+2])//3
    b[j] = b[j+1] = b[j+2] = g
bind(h)


from time import time

fs = {'f':f, 'g':g, 'h':h}

def t(f,b):
  F = fs[f]
  st = time()
  F(b)
  et = time()
  print "%s: %s" % (f, et-st)

b = range(30000)

from array import array
c = array('i',b)
t('f',c)
t('g',c)
t('h',c)
t('f',c)
t('g',c)
t('h',c)

outputs

f: 0.0158488750458
g: 0.000610113143921
h: 0.00200295448303
f: 0.0184948444366
g: 0.000257015228271
h: 0.00116610527039

-- 
David C. Ullrich



More information about the Python-list mailing list