def _sig_gemv(self, ops, A_js_fn, X_js_fn, Y_fn, Y_in_fn=None, alpha=1.0, beta=1.0, gamma=0.0, tag=None): if len(ops) == 0: return [] all_data, sidx = self.all_data, self.sidx A_js = RaggedArray([[sidx[ss] for ss in A_js_fn(op)] for op in ops]) X_js = RaggedArray([[sidx[ss] for ss in X_js_fn(op)] for op in ops]) Y_sigs = [Y_fn(item) for item in ops] Y_in_sigs = [Y_in_fn(item) for item in ops] if Y_in_fn else Y_sigs Y = all_data[[sidx[sig] for sig in Y_sigs]] Y_in = all_data[[sidx[sig] for sig in Y_in_sigs]] if callable(beta): beta = RaggedArray([sidx[beta(o)] for o in ops], dtype=np.float32) rval = plan_block_gemv(self.queue, alpha, all_data, A_js, all_data, X_js, beta, Y, Y_in=Y_in, gamma=gamma, tag=tag) return rval.plans
def to_host(self): """Copy the whole object to a host RaggedArray""" return RaggedArray.from_buffer(self.buf, self.starts, self.shape0s, self.shape1s, self.stride0s, self.stride1s, names=self.names)
def to_host(self): """Copy the whole object to a host RaggedArray""" rval = RaggedArray.__new__(RaggedArray) rval.starts = self.starts.tolist() rval.shape0s = self.shape0s.tolist() rval.shape1s = self.shape1s.tolist() rval.stride0s = self.stride0s.tolist() rval.stride1s = self.stride1s.tolist() rval.buf = self.buf rval.names = self.names[:] return rval
def _plan_LinearFilter(self, ops): steps = [ op.process.make_step(op.input.shape, op.output.shape, self.model.dt, rng=None) for op in ops ] A = self.RaggedArray([f.den for f in steps], dtype=np.float32) B = self.RaggedArray([f.num for f in steps], dtype=np.float32) X = self.all_data[[self.sidx[op.input] for op in ops]] Y = self.all_data[[self.sidx[op.output] for op in ops]] Xbuf0 = RaggedArray( [np.zeros(shape) for shape in zip(B.sizes, X.sizes)], dtype=np.float32) Ybuf0 = RaggedArray( [np.zeros(shape) for shape in zip(A.sizes, Y.sizes)], dtype=np.float32) Xbuf = CLRaggedArray(self.queue, Xbuf0) Ybuf = CLRaggedArray(self.queue, Ybuf0) self._raggedarrays_to_reset[Xbuf] = Xbuf0 self._raggedarrays_to_reset[Ybuf] = Ybuf0 return plan_linearfilter(self.queue, X, Y, A, B, Xbuf, Ybuf)
def from_arrays(cls, queue, arrays, names=None, dtype=None, align=False): return cls(queue, RaggedArray(arrays, names=names, dtype=dtype, align=align))
def __init__(self, network, dt=0.001, seed=None, model=None, context=None, n_prealloc_probes=32, profiling=None, if_python_code='none', planner=greedy_planner, progress_bar=True): # --- check version if nengo.version.version_info in bad_nengo_versions: raise ValueError( "This simulator does not support Nengo version %s. Upgrade " "with 'pip install --upgrade --no-deps nengo'." % nengo.__version__) elif nengo.version.version_info > latest_nengo_version_info: warnings.warn("This version of `nengo_ocl` has not been tested " "with your `nengo` version (%s). The latest fully " "supported version is %s" % (nengo.__version__, latest_nengo_version)) # --- create these first since they are used in __del__ self.closed = False self.model = None # --- arguments/attributes if context is None and Simulator.some_context is None: print('No context argument was provided to nengo_ocl.Simulator') print("Calling pyopencl.create_some_context() for you now:") Simulator.some_context = cl.create_some_context() if profiling is None: profiling = int(os.getenv("NENGO_OCL_PROFILING", 0)) self.context = Simulator.some_context if context is None else context self.profiling = profiling self.queue = cl.CommandQueue( self.context, properties=PROFILING_ENABLE if self.profiling else 0) if if_python_code not in ['none', 'warn', 'error']: raise ValueError("%r not a valid value for `if_python_code`" % if_python_code) self.if_python_code = if_python_code self.n_prealloc_probes = n_prealloc_probes self.progress_bar = progress_bar # --- Nengo build with Timer() as nengo_timer: if model is None: self.model = Model(dt=float(dt), label="%s, dt=%f" % (network, dt), decoder_cache=get_default_decoder_cache()) else: self.model = model if network is not None: # Build the network into the model self.model.build(network) logger.info("Nengo build in %0.3f s" % nengo_timer.duration) # --- operators with Timer() as planner_timer: operators = list(self.model.operators) # convert DotInc and Copy to MultiDotInc operators = list(map(MultiDotInc.convert_to, operators)) operators = MultiDotInc.compress(operators) # plan the order of operations, combining where appropriate op_groups = planner(operators) assert len([typ for typ, _ in op_groups if typ is Reset ]) < 2, ("All resets not planned together") self.operators = operators self.op_groups = op_groups logger.info("Planning in %0.3f s" % planner_timer.duration) with Timer() as signals_timer: # Initialize signals all_signals = stable_unique(sig for op in operators for sig in op.all_signals) all_bases = stable_unique(sig.base for sig in all_signals) sigdict = SignalDict() # map from Signal.base -> ndarray for op in operators: op.init_signals(sigdict) # Add built states to the probe dictionary self._probe_outputs = dict(self.model.params) # Provide a nicer interface to probe outputs self.data = ProbeDict(self._probe_outputs) # Create data on host and add views self.all_data = RaggedArray( [sigdict[sb] for sb in all_bases], names=[getattr(sb, 'name', '') for sb in all_bases], dtype=np.float32) view_builder = ViewBuilder(all_bases, self.all_data) view_builder.setup_views(operators) for probe in self.model.probes: view_builder.append_view(self.model.sig[probe]['in']) view_builder.add_views_to(self.all_data) self.all_bases = all_bases self.sidx = { k: np.int32(v) for k, v in iteritems(view_builder.sidx) } self._A_views = view_builder._A_views self._X_views = view_builder._X_views self._YYB_views = view_builder._YYB_views del view_builder # Copy data to device self.all_data = CLRaggedArray(self.queue, self.all_data) logger.info("Signals in %0.3f s" % signals_timer.duration) # --- set seed self.seed = np.random.randint(npext.maxint) if seed is None else seed self.rng = np.random.RandomState(self.seed) # --- create list of plans self._raggedarrays_to_reset = {} self._cl_rngs = {} self._python_rngs = {} plans = [] with Timer() as plans_timer: for op_type, op_list in op_groups: plans.extend(self.plan_op_group(op_type, op_list)) plans.extend(self.plan_probes()) logger.info("Plans in %0.3f s" % plans_timer.duration) # -- create object to execute list of plans self._plans = Plans(plans, self.profiling) self.rng = None # all randomness set, should no longer be used self._reset_probes() # clears probes from previous model builds
def sig_gemv(self, seq, alpha, A_js_fn, X_js_fn, beta, Y_sig_fn, Y_in_sig_fn=None, gamma=None, verbose=0, tag=None): if len(seq) == 0: return [] sidx = self.sidx if callable(beta): beta_sigs = list(map(beta, seq)) beta = RaggedArray(list(map(sidx.__getitem__, beta_sigs)), dtype=np.float32) Y_sigs = [Y_sig_fn(item) for item in seq] if Y_in_sig_fn is None: Y_in_sigs = Y_sigs else: Y_in_sigs = [Y_in_sig_fn(item) for item in seq] Y_idxs = [sidx[sig] for sig in Y_sigs] Y_in_idxs = [sidx[sig] for sig in Y_in_sigs] # -- The following lines illustrate what we'd *like* to see... # # A_js = RaggedArray( # [[sidx[ss] for ss in A_js_fn(item)] for item in seq]) # X_js = RaggedArray( # [[sidx[ss] for ss in X_js_fn(item)] for item in seq]) # # -- ... but the simulator supports broadcasting. So in fact whenever # a signal in X_js has shape (N, 1), the corresponding A_js signal # can have shape (M, N) or (1, 1). # Fortunately, scalar multiplication of X by A can be seen as # Matrix multiplication of A by X, so we can still use gemv, # we just need to reorder and transpose. A_js = [] X_js = [] for ii, item in enumerate(seq): A_js_i = [] X_js_i = [] A_sigs_i = A_js_fn(item) X_sigs_i = X_js_fn(item) assert len(A_sigs_i) == len(X_sigs_i) for asig, xsig in zip(A_sigs_i, X_sigs_i): A_js_i.append(sidx[asig]) X_js_i.append(sidx[xsig]) A_js.append(A_js_i) X_js.append(X_js_i) if verbose: print("in sig_vemv") print("print A", A_js) print("print X", X_js) A_js = RaggedArray(A_js, dtype=np.int32) X_js = RaggedArray(X_js, dtype=np.int32) Y = self.all_data[Y_idxs] Y_in = self.all_data[Y_in_idxs] rval = self.plan_ragged_gather_gemv( alpha=alpha, A=self.all_data, A_js=A_js, X=self.all_data, X_js=X_js, beta=beta, Y=Y, Y_in=Y_in, tag=tag, seq=seq, gamma=gamma, ) try: return rval.plans except AttributeError: return [rval]
def __init__(self, network, dt=0.001, seed=None, model=None, planner=greedy_planner): with Timer() as nengo_timer: if model is None: self.model = Model(dt=float(dt), label="%s, dt=%f" % (network, dt), decoder_cache=get_default_decoder_cache()) else: self.model = model if network is not None: # Build the network into the model self.model.build(network) logger.info("Nengo build in %0.3f s" % nengo_timer.duration) # --- set seed seed = np.random.randint(npext.maxint) if seed is None else seed self.seed = seed self.rng = np.random.RandomState(self.seed) self._step = Signal(np.array(0.0, dtype=np.float64), name='step') self._time = Signal(np.array(0.0, dtype=np.float64), name='time') # --- operators with Timer() as planner_timer: operators = list(self.model.operators) # convert DotInc, Reset, Copy, and ProdUpdate to MultiProdUpdate operators = list(map(MultiProdUpdate.convert_to, operators)) operators = MultiProdUpdate.compress(operators) # plan the order of operations, combining where appropriate op_groups = planner(operators) assert len([typ for typ, _ in op_groups if typ is Reset ]) < 2, ("All resets not planned together") # add time operator after planning, to ensure it goes first time_op = TimeUpdate(self._step, self._time) operators.insert(0, time_op) op_groups.insert(0, (type(time_op), [time_op])) self.operators = operators self.op_groups = op_groups logger.info("Planning in %0.3f s" % planner_timer.duration) with Timer() as signals_timer: # Initialize signals all_signals = signals_from_operators(operators) all_bases = stable_unique([sig.base for sig in all_signals]) sigdict = SignalDict() # map from Signal.base -> ndarray for op in operators: op.init_signals(sigdict) # Add built states to the probe dictionary self._probe_outputs = self.model.params # Provide a nicer interface to probe outputs self.data = ProbeDict(self._probe_outputs) self.all_data = RaggedArray( [sigdict[sb] for sb in all_bases], [getattr(sb, 'name', '') for sb in all_bases], dtype=np.float32) builder = ViewBuilder(all_bases, self.all_data) self._AX_views = {} self._YYB_views = {} for op_type, op_list in op_groups: self.setup_views(builder, op_type, op_list) for probe in self.model.probes: builder.append_view(self.model.sig[probe]['in']) builder.add_views_to(self.all_data) self.all_bases = all_bases self.sidx = builder.sidx self._prep_all_data() logger.info("Signals in %0.3f s" % signals_timer.duration) # --- create list of plans with Timer() as plans_timer: self._plan = [] for op_type, op_list in op_groups: self._plan.extend(self.plan_op_group(op_type, op_list)) self._plan.extend(self.plan_probes()) logger.info("Plans in %0.3f s" % plans_timer.duration) self.n_steps = 0
from nengo_ocl import raggedarray as ra from nengo_ocl.clra_nonlinearities import ( plan_copy, plan_elementwise_inc, plan_lif, plan_lif_rate, plan_linearfilter, plan_reset, plan_slicedcopy, ) from nengo_ocl.clraggedarray import CLRaggedArray as CLRA from nengo_ocl.clraggedarray import to_device from nengo_ocl.raggedarray import RaggedArray logger = logging.getLogger(__name__) RA = lambda arrays, dtype=np.float32: RaggedArray(arrays, dtype=dtype) def not_close(a, b, rtol=1e-3, atol=1e-3): return np.abs(a - b) > atol + rtol * np.abs(b) @pytest.mark.parametrize("upsample", [1, 4]) def test_lif_step(ctx, upsample): """Test the lif nonlinearity, comparing one step with the Numpy version.""" rng = np.random dt = 1e-3 n_neurons = [12345, 23456, 34567] J = RA([rng.normal(scale=1.2, size=n) for n in n_neurons]) V = RA([rng.uniform(low=0, high=1, size=n) for n in n_neurons])
def to_host(self): """Copy the whole object to a host RaggedArray""" return RaggedArray.from_buffer( self.buf, self.starts, self.shape0s, self.shape1s, self.stride0s, self.stride1s, names=self.names)