Package topo :: Package responsefn :: Module optimized
[hide private]
[frames] | no frames]

Source Code for Module topo.responsefn.optimized

  1  """ 
  2  Response functions (see basic.py) and CFProjection response functions 
  3  (see projfn.py) written in C to optimize performance. 
  4   
  5  Requires the weave package; without it unoptimized versions are used. 
  6   
  7  $Id: optimized.py 11088 2010-06-17 17:23:59Z ceball $ 
  8  """ 
  9  __version__='$Revision: 11088 $' 
 10   
 11  import param 
 12   
 13  from topo.base.functionfamily import ResponseFn,DotProduct 
 14  from topo.base.cf import CFPResponseFn, CFPRF_Plugin 
 15  from topo.misc.inlinec import inline,provide_unoptimized_equivalent,c_header 
 16  from topo.responsefn.projfn import CFPRF_EuclideanDistance 
 17   
 18   
 19       
 20   
 21  # CEBALERT: the "only works for 1D array" doc is out of date, right? 
 22  # Should remove from here and other optimized fns that have been 
 23  # flattened. 
24 -class CFPRF_DotProduct_opt(CFPResponseFn):
25 """ 26 Dot-product response function. 27 28 Written in C for a manyfold speedup; see CFPRF_DotProduct for an 29 easier-to-read version in Python. The unoptimized Python version 30 is equivalent to this one, but it also works for 1D arrays. 31 """ 32 33 single_cf_fn = param.ClassSelector(ResponseFn,DotProduct(),readonly=True) 34
35 - def __call__(self, iterator, input_activity, activity, strength, **params):
36 37 temp_act = activity 38 irows,icols = input_activity.shape 39 X = input_activity.ravel() 40 cfs = iterator.flatcfs 41 num_cfs = len(cfs) 42 mask = iterator.mask.data 43 44 cf_type = iterator.cf_type 45 46 code = c_header + """ 47 DECLARE_SLOT_OFFSET(weights,cf_type); 48 DECLARE_SLOT_OFFSET(input_sheet_slice,cf_type); 49 50 npfloat *tact = temp_act; 51 52 for (int r=0; r<num_cfs; ++r) { 53 if((*mask++) == 0.0) 54 *tact = 0; 55 else { 56 PyObject *cf = PyList_GetItem(cfs,r); 57 58 CONTIGUOUS_ARRAY_FROM_SLOT_OFFSET(float,weights,cf) 59 LOOKUP_FROM_SLOT_OFFSET(int,input_sheet_slice,cf); 60 61 UNPACK_FOUR_TUPLE(int,rr1,rr2,cc1,cc2,input_sheet_slice); 62 63 double tot = 0.0; 64 npfloat *xj = X+icols*rr1+cc1; 65 66 // computes the dot product 67 for (int i=rr1; i<rr2; ++i) { 68 npfloat *xi = xj; 69 float *wi = weights; 70 for (int j=cc1; j<cc2; ++j) { 71 tot += *wi * *xi; 72 ++wi; 73 ++xi; 74 } 75 xj += icols; 76 weights += cc2-cc1; 77 } 78 *tact = tot*strength; 79 80 DECREF_CONTIGUOUS_ARRAY(weights); 81 } 82 ++tact; 83 } 84 """ 85 inline(code, ['mask','X', 'strength', 'icols', 'temp_act','cfs','num_cfs','cf_type'], 86 local_dict=locals(), headers=['<structmember.h>'])
87
88 -class CFPRF_DotProduct(CFPRF_Plugin):
89 """ 90 Wrapper written to allow transparent non-optimized fallback; 91 equivalent to CFPRF_Plugin(single_cf_fn=DotProduct()). 92 """ 93 # CB: should probably have single_cf_fn here & readonly
94 - def __init__(self,**params):
96 97 provide_unoptimized_equivalent("CFPRF_DotProduct_opt","CFPRF_DotProduct",locals()) 98 99 100 # CEBERRORALERT: ignores the sheet mask!
101 -class CFPRF_EuclideanDistance_opt(CFPResponseFn):
102 """ 103 Euclidean-distance response function. 104 105 Written in C for a several-hundred-times speedup; see 106 CFPRF_EuclideanDistance for an easier-to-read (but otherwise 107 equivalent) version in Python. 108 """
109 - def __call__(self, iterator, input_activity, activity, strength, **params):
110 temp_act = activity 111 rows,cols = activity.shape 112 irows,icols = input_activity.shape 113 X = input_activity.ravel() 114 cfs = iterator.flatcfs 115 num_cfs = len(cfs) 116 117 code = c_header + """ 118 #include <math.h> 119 npfloat *tact = temp_act; 120 double max_dist=0.0; 121 122 for (int r=0; r<num_cfs; ++r) { 123 PyObject *cf = PyList_GetItem(cfs,r); 124 125 PyObject *weights_obj = PyObject_GetAttrString(cf,"weights"); 126 PyObject *slice_obj = PyObject_GetAttrString(cf,"input_sheet_slice"); 127 128 float *wj = (float *)(((PyArrayObject*)weights_obj)->data); 129 int *slice = (int *)(((PyArrayObject*)slice_obj)->data); 130 131 int rr1 = *slice++; 132 int rr2 = *slice++; 133 int cc1 = *slice++; 134 int cc2 = *slice; 135 136 npfloat *xj = X+icols*rr1+cc1; 137 138 // computes the dot product 139 double tot = 0.0; 140 for (int i=rr1; i<rr2; ++i) { 141 npfloat *xi = xj; 142 float *wi = wj; 143 for (int j=cc1; j<cc2; ++j) { 144 double diff = *wi - *xi; 145 tot += diff*diff; 146 ++wi; 147 ++xi; 148 } 149 xj += icols; 150 wj += cc2-cc1; 151 } 152 153 double euclidean_distance = sqrt(tot); 154 if (euclidean_distance>max_dist) 155 max_dist = euclidean_distance; 156 157 *tact = euclidean_distance; 158 ++tact; 159 160 // Anything obtained with PyObject_GetAttrString must be explicitly freed 161 Py_DECREF(weights_obj); 162 Py_DECREF(slice_obj); 163 } 164 tact = temp_act; 165 for (int r=0; r<num_cfs; ++r) { 166 *tact = strength*(max_dist - *tact); 167 ++tact; 168 } 169 """ 170 inline(code, ['X', 'strength', 'icols', 'temp_act','cfs','num_cfs'], 171 local_dict=locals())
172 173 provide_unoptimized_equivalent("CFPRF_EuclideanDistance_opt","CFPRF_EuclideanDistance",locals()) 174