[SciPy-user] Help with array functions

eric jones eric at enthought.com
Tue May 4 11:31:52 CDT 2004


So, try two...

I don't know of a pure Python solution either.  My next option is 
usually playing around in weave.  Here is a weave snippet that 
implements the algorithm in C.  It runs, but just like the last one is 
untested.  Given the track record here, a decent test is advisable... :-) 

Here is the output from my cursory check to see if the code would work:

C:\temp>wv.py
weave results:  [ 0. 0.8 0.96 0.992 0.9984  0.99968  0.999936  
0.9999872  0.99999744  1.]
python results: [ 0. 0.8 0.96 0.992 0.9984  0.99968  0.999936  
0.9999872  0.99999744  1.]
C time: 0.00707567096418
Python time: 0.316835262617
weave vs. Python speedup: 44.7781226997

This is using gcc as the compiler in weave and 2048 samples in a 
signal.  If you drop to 256, the improvement is cut in half.

Now the code:

# test.py
from scipy import zeros, ones, Float64, arange
from scipy import stats
import weave

def python_algorithm(gain, complexout, attack, peak, level, samples):
    # gain is changed *inplace*
    i = arange(1,samples)
    for x in i:
        if abs(complexout[x-1]) > 0:
           gain[x] = ( (gain[x-1] * (1.0 - attack)) + ((attack * peak) / 
abs(complexout[x-1])) )       
           if gain[x] > level:
               gain[x] = level
        else:
           gain[x] = 1

def weave_algorithm(gain, complexout, attack, peak, level, samples):
    # gain is changed *inplace*
    code = """
           for (int x=1; x < samples; x++)
           {
               if (abs(complexout[x-1]) > 0.0)
               {
                  gain[x] = ( (gain[x-1] * (1.0 - attack)) +
                              ((attack * peak) / abs(complexout[x-1])) 
);       
                  if (gain[x] > level)
                      gain[x] = level;
               }
               else          
                  gain[x] = 1;
           }
           """
   
    weave.inline(code,
                 ['gain', 'complexout', 'samples', 'attack', 'peak', 
'level'],
                 compiler='gcc')
   

# some default parameters...
samples = 2048
gain = zeros(samples,typecode=Float64)
complexout = stats.choice([-1.0,0.0,1.0],size=samples)

attack = .8
peak = 1.0
level = 1.0


# equivalence tests
weave_algorithm(gain, complexout, attack, peak, level, samples)
print 'weave results:', gain[:10]

gain = zeros(samples,typecode=Float64)
python_algorithm(gain, complexout, attack, peak, level, samples)
print 'python results:', gain[:10]


# speed tests
import time

N = 100

t1 = time.clock()
for it in range(N):
    weave_algorithm(gain, complexout, attack, peak, level, samples)
t2 = time.clock()
ct = t2 - t1
print 'C time:', ct

t1 = time.clock()
for it in range(N):
    python_algorithm(gain, complexout, attack, peak, level, samples)
t2 = time.clock()
pt = t2-t1
print 'Python time:', pt

ratio = pt/ct
print 'weave vs. Python speedup:', ratio


eric jones wrote:

> Yikes.  Your right!
>
> eric
>
> Perry Greenfield wrote:
>
>> Eric Jones wrote:
>>  
>>
>>> Bob.Cowdery at CGI-Europe.com wrote:
>>>
>>> The general ideas of uisng Numeric in Python is to avoid loops, even 
>>> at the expense of sometimes doing extra computations.  In this case, 
>>> the signal processing calculations can be done for every entry in 
>>> the array (except the first).  The conditions checked for in the 
>>> "if" statements can then be filtered out in subsequent array 
>>> processing steps.
>>>
>>>
>>> Here is some (totally untested) code that should give you some ideas:
>>>
>>>    gain = self.m_procGain
>>>    abs_complexout = abs(self.m_complexout)
>>>
>>>    # Do singal processing calculation for all elements in array
>>>    gain[1:] = ( (gain[:-1] * (1 - attack)) +
>>>                 ((attack * peak) / abs_complexout[:-1]) )
>>>
>>>   
>>
>> Does this do what is needed? I think the point he was making
>> was that gain[i] depends on gain[i-1] which in turn depends
>> on gain[i-2] and so on. The expression above doesn't capture that
>> since from his code he doesn't show any initial value for gain
>> (implicitly the gain[0] must exist). So using an array expression
>> which uses a shifted gain array in its input won't work.
>> This is the sort of problem that doesn't fit the array model
>> very well unless there are some primitive array operations
>> that happen to do the iterative thing needed (sometimes
>> the accumulate or convolve functions can be used for this
>> thing, but I can't see any obvious existing function. Seems
>> like a candidate for a C extension but maybe I'm missing something.
>>
>> Perry
>>  
>>
>>
>> _______________________________________________
>> SciPy-user mailing list
>> SciPy-user at scipy.net
>> http://www.scipy.net/mailman/listinfo/scipy-user
>>  
>>
>
>
> _______________________________________________
> SciPy-user mailing list
> SciPy-user at scipy.net
> http://www.scipy.net/mailman/listinfo/scipy-user





More information about the SciPy-user mailing list