brian-team / brian2

Brian is a free, open source simulator for spiking neural networks.
http://briansimulator.org
Other
941 stars 221 forks source link

SpikeGeneratorGroup sorting is very slow #948

Closed thesamovar closed 6 years ago

thesamovar commented 6 years ago

The problem is in SpikeGeneratorGroup.__init__ and before_run (and also duplicated code in set_spikes) like this:

        if not sorted:
            # sort times and indices first by time, then by indices
            rec = np.rec.fromarrays([times, indices], names=['t', 'i'])
            rec.sort()
            times = np.ascontiguousarray(rec.t)
            indices = np.ascontiguousarray(rec.i)

and

            shift = 1e-3*dt
            timebins = np.asarray(np.asarray(self._spike_time + shift)/dt,
                                  dtype=np.int32)
            index_timebins = np.rec.fromarrays([self._neuron_index,
                                                timebins], names=['i', 't'])
            if not len(np.unique(index_timebins)) == len(timebins):
                raise ValueError('Using a dt of %s, some neurons of '
                                 'SpikeGeneratorGroup "%s" spike more than '
                                 'once during a time step.' % (str(self.dt),
                                                               self.name))
            self._previous_dt = dt
            self._spikes_changed = False

Huge amounts of time are spent in ndarray.sort() and unique. The problem appears to be the use of recarrays, which are apparently very slow. For the first code block, it can be replaced with this code and is much faster:

I = lexsort((indices, times))
indices = indices[I]
times = times[I]

In some code I was working on, the time drops from 90s to about 17s.

I will submit a PR soon since it shouldn't take long to implement this.

mstimberg commented 6 years ago

Good catch, I think I never used big enough SpikeGeneratorGroups to notice this. Probably there's a faster implementation of the unique check as well?

thesamovar commented 6 years ago

Working on this now. Incidentally, the code I was working on had around 60M spikes being sent to SpikeGeneratorGroup so it's not surprising we didn't really notice this before!

mstimberg commented 6 years ago

Cool. BTW: are your 60M spikes unsorted in the first place? If not, don't forget the sorted=True option :)