def _plan_fn_in_ocl(self, fn, tt, xx, yy, fn_name): signal_size = lambda sig: sig.size if sig is not None else None vector_dims = lambda shape, dim: len(shape) == 1 and shape[0] == dim unit_stride = lambda s, es: len(es) == 1 and (s[0] == 1 or es[0] == 1) t_in = tt[0] is not None x_in = xx[0] is not None x_dim = signal_size(xx[0]) y_dim = signal_size(yy[0]) assert x_dim != 0 and y_dim != 0 # should either be None or > 0 assert all(signal_size(x) == x_dim for x in xx) assert all(signal_size(y) == y_dim for y in yy) # check signal input and output shape (implicitly checks # for indexing errors) if x_in: assert all(vector_dims(x.shape, x_dim) for x in xx) assert all(unit_stride(x.shape, x.elemstrides) for x in xx) assert all(vector_dims(y.shape, y_dim) for y in yy) assert all(unit_stride(y.shape, y.elemstrides) for y in yy) # try to get OCL code in_dims = ([1] if t_in else []) + ([x_dim] if x_in else []) ocl_fn = OCL_Function(fn, in_dims=in_dims, out_dim=y_dim) input_names = ocl_fn.translator.arg_names inputs = [] if t_in: # append time inputs.append(self.all_data[[self.sidx[t] for t in tt]]) if x_in: # append x inputs.append(self.all_data[[self.sidx[x] for x in xx]]) output = self.all_data[[self.sidx[y] for y in yy]] return plan_direct(self.queue, ocl_fn.code, ocl_fn.init, input_names, inputs, output, tag=fn_name)
def plan_SimPyFunc(self, ops): # TODO: test with a hybrid program (Python and OCL) # group nonlinearities unique_ops = OrderedDict() for op in ops: # assert op.n_args in (1, 2), op.n_args op_key = (op.fn, op.t_in, op.x is not None) if op_key not in unique_ops: unique_ops[op_key] = {'in': [], 'out': []} unique_ops[op_key]['in'].append(op.x) unique_ops[op_key]['out'].append(op.output) # make plans plans = [] for (fn, t_in, x_in), signals in unique_ops.items(): fn_name = (fn.__name__ if inspect.isfunction(fn) else fn.__class__.__name__) if fn_name == "<lambda>": fn_name += "%d" % len(plans) # check signal input and output shape (implicitly checks # for indexing errors) vector_dims = lambda shape, dim: len( shape) == 1 and shape[0] == dim unit_stride = lambda es: len(es) == 1 and es[0] == 1 if x_in: in_dim = signals['in'][0].size for sig_in in signals['in']: assert sig_in.size == in_dim assert vector_dims(sig_in.shape, in_dim) assert unit_stride(sig_in.elemstrides) else: in_dim = None # if any functions have no output, must do them in Python if any(s is None for s in signals['out']): assert all(s is None for s in signals['out']) warnings.warn( "Function '%s' could not be converted to OCL since it has " "no outputs." % (fn_name), RuntimeWarning) plans.append(self._plan_pythonfn( fn, t_in, signals, fn_name=fn_name)) continue out_dim = signals['out'][0].size for sig_out in signals['out']: assert sig_out.size == out_dim assert vector_dims(sig_out.shape, out_dim) assert unit_stride(sig_out.elemstrides) # try to get OCL code try: in_dims = [1] if t_in else [] in_dims += [in_dim] if x_in else [] ocl_fn = OCL_Function(fn, in_dims=in_dims, out_dim=out_dim) input_names = ocl_fn.translator.arg_names inputs = [] if t_in: # append time inputs.append(self.all_data[ [self.sidx[self._time] for i in signals['out']]]) if x_in: # append x inputs.append(self.all_data[ [self.sidx[i] for i in signals['in']]]) output = self.all_data[[self.sidx[i] for i in signals['out']]] plan = plan_direct(self.queue, ocl_fn.code, ocl_fn.init, input_names, inputs, output, tag=fn_name) plans.append(plan) except Exception as e: if self.ocl_only: raise warnings.warn( "Function '%s' could not be converted to OCL due to %s%s" % (fn_name, e.__class__.__name__, e.args), RuntimeWarning) # not successfully translated to OCL, so do it in Python plans.append(self._plan_pythonfn( fn, t_in, signals, fn_name=fn_name)) return plans
def plan_SimPyFunc(self, ops): # TODO: test with a hybrid program (Python and OCL) # group nonlinearities unique_ops = OrderedDict() for op in ops: # assert op.n_args in (1, 2), op.n_args op_key = (op.fn, op.t_in, op.x is not None) if op_key not in unique_ops: unique_ops[op_key] = {'in': [], 'out': []} unique_ops[op_key]['in'].append(op.x) unique_ops[op_key]['out'].append(op.output) # make plans plans = [] for (fn, t_in, x_in), signals in unique_ops.items(): fn_name = (fn.__name__ if inspect.isfunction(fn) else fn.__class__.__name__) if fn_name == "<lambda>": fn_name += "%d" % len(plans) # check signal input and output shape (implicitly checks # for indexing errors) vector_dims = lambda shape, dim: len(shape) == 1 and shape[0 ] == dim unit_stride = lambda es: len(es) == 1 and es[0] == 1 if x_in: in_dim = signals['in'][0].size for sig_in in signals['in']: assert sig_in.size == in_dim assert vector_dims(sig_in.shape, in_dim) assert unit_stride(sig_in.elemstrides) else: in_dim = None # if any functions have no output, must do them in Python if any(s is None for s in signals['out']): assert all(s is None for s in signals['out']) warnings.warn( "Function '%s' could not be converted to OCL since it has " "no outputs." % (fn_name), RuntimeWarning) plans.append( self._plan_pythonfn(fn, t_in, signals, fn_name=fn_name)) continue out_dim = signals['out'][0].size for sig_out in signals['out']: assert sig_out.size == out_dim assert vector_dims(sig_out.shape, out_dim) assert unit_stride(sig_out.elemstrides) # try to get OCL code try: in_dims = [1] if t_in else [] in_dims += [in_dim] if x_in else [] ocl_fn = OCL_Function(fn, in_dims=in_dims, out_dim=out_dim) input_names = ocl_fn.translator.arg_names inputs = [] if t_in: # append time inputs.append(self.all_data[[ self.sidx[self._time] for i in signals['out'] ]]) if x_in: # append x inputs.append( self.all_data[[self.sidx[i] for i in signals['in']]]) output = self.all_data[[self.sidx[i] for i in signals['out']]] plan = plan_direct(self.queue, ocl_fn.code, ocl_fn.init, input_names, inputs, output, tag=fn_name) plans.append(plan) except Exception as e: if self.ocl_only: raise warnings.warn( "Function '%s' could not be converted to OCL due to %s%s" % (fn_name, e.__class__.__name__, e.args), RuntimeWarning) # not successfully translated to OCL, so do it in Python plans.append( self._plan_pythonfn(fn, t_in, signals, fn_name=fn_name)) return plans