map

Fernando Perez fperez528 at yahoo.com
Fri Jun 7 21:24:47 CEST 2002


Giorgi Lekishvili wrote:

> Hi all!
> 
> Is there a way to map a function with several arguments to a list? E.g.,
> 
>>>>import math
>>>>import MLab
>>>>a=MLab.rand(3,5)
>>>>b=map(math.pow,a)
> 
> of course, this doesn't work.
> 
> What to do? My task is to optimize the power (i.e., y in pow(x,y)) to
> achieve maximal performance.
> 
> 
> thanx,
> Giorgi
> 
> PS: Perhaps I have missed the needed functionality, that's presented in
> NumPy?

It's hard to tell what you're trying to do, since a 3x5 array doesn't have an 
'obvious' way to be used as an argument to pow. But anyway, for 'maximal 
performance' you should use NumPy the way it was meant to be used. It already 
overloads ** so you can just write:

In [1]: import MLab

In [2]: a=MLab.rand(3,5)

In [3]: a
Out[3]:
array([[ 0.7906459 ,  0.9962979 ,  0.59841698,  0.13870062,  0.93503422],
       [ 0.03783634,  0.68916065,  0.79217309,  0.23443535,  0.87729597],
       [ 0.04226565,  0.4821128 ,  0.8859337 ,  0.45935223,  0.47994375]])

In [4]: a**3
Out[4]:
array([[  4.94249303e-01,   9.88934754e-01,   2.14294850e-01,   
2.66830335e-03,
               8.17490114e-01],
       [  5.41660550e-05,   3.27311607e-01,   4.97118874e-01,   
1.28845512e-02,
               6.75209283e-01],
       [  7.55027297e-05,   1.12058801e-01,   6.95350325e-01,   
9.69253713e-02,
               1.10553126e-01]])


As a rule of thumb, in Numeric NEVER roll your own loops (even using map). 
Right there you kill all of the speed advantage of NumPy. If you can't find a 
way to write things with Numeric's functions and absolutely need to loop by 
hand, it will be dog slow. At that point, your only option is to write the 
tight loops in C, which is actually extremely easy to do using weave 
(http://scipy.org)

Here's a quick comparison showing the disaster you're heading into if you try 
to use loops/map instead of properly using numeric:

In [1]: import MLab, Numeric

In [2]: def loop_pow3(arr):
   ...:   out = Numeric.zeros(len(arr),arr.typecode())
   ...:   for i in xrange(len(arr)):
   ...:     out[i] = arr[i]**3
   ...:   return out
   ...:

In [3]: numpow3 = lambda x:x**3

In [4]: pow3=lambda x: pow(x,3)

In [5]: a=MLab.rand(100000)

In [6]: time_test (1,numpow3,a)
Out[6]: 0.070000000000000062

In [7]: time_test (1,map,pow3,a)
Out[7]: 1.1199999999999999

In [8]: time_test (1,loop_pow3,a)
Out[8]: 0.54000000000000004

In [9]: _7/_6
Out[9]: 15.999999999999984

In [10]: _8/_6
Out[10]: 7.7142857142857082

So in summary, using map is a factor of 16 slower than using Numeric's 
builtin operators (or rather its natural overloading of **) and using loops 
is a factor of 8 slower.

Unless you have a lot of time to sit around and wait, I'd recommmend spending 
an hour or two cuddled up with the Numeric documentation. It's a complete (if 
'creatively' organized ;) reference.

Cheers,

f.



More information about the Python-list mailing list