-
Notifications
You must be signed in to change notification settings - Fork 223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Efficient synapse creation #65
Comments
Ok, I have to put some thought into this. Might also be interesting to look at the connection-set algebra implementation for inspiration. Will be back tomorrow with some feedback. |
Ok, no real feedback yet... But I'm thinking that we should maybe restrict efficient approaches to correct use of the |
I agree we don't need to prioritise this - I marked it for the beta release rather than the alpha/dev-preview release. I'd rather everything worked with the string conditions, and that actually things like the |
I think in our e-mail discussion with Romain the idea (his idea at least ;) ) was to make all the options combine, e.g. instead of writing
Separating it into and/or components seems easy enough, I'm more concerned with analysing the form, e.g. would we recognize not only 'i == j' but also '(i-100) == j', etc.? I'm a bit worried that in the end it will not be entirely clear for a user under what circumstances expressions will be treated efficiently. Anyway, let's discuss this in more detail post-Alpha :) |
Well we didn't really discuss that idea much. What do you think about it? I feel it's less explicit and doesn't save much typing. For analysing the form, I think it's ok if we incrementally improve the recognised forms over time. The only critical ones are But yes, let's leave it for the moment and just go with the O(N^2) technique for now. |
I kind of like the idea, it separates strict conditions (e.g. "no self-connections") from probabilities (e.g. "Gaussian connection probability depending on distance"), joining all together with |
OK, if you both prefer it I don't mind being overruled on this! |
An even simpler suggestion. We allow the user to specify a function |
I'm not sure I 100% understand this proposal -- how does this connect to your general suggestion of parsing and analyzing the string? Just to copy here my remark I made in an email a while ago so that it doesn't get lost: # One-to-one-connectivity, loops over all i
S.connect_each_source_to('i')
# Connect each cell to its two neighbours, "counter" runs automatically
# from 0 to n-1
S.connect_each_source_to('i + (-1)**counter', n=2) |
It doesn't connect to it - it's an alternative. The advantage of specifying a range of values to consider is that you can do combined operations like connect i to j if |
Ok, I just wondered because you said "I mildly prefer my general suggestion above (which would include this as a specific optimisation)" above. Anyway, this would be a big addition that really needs some careful thought. |
Indeed - let's think about it another time! |
I just had a few thoughts on this. Firstly, we could make a potentially enormous optimisation that is quite general. If the set of indices used in an expression are only i or only j (and there are no stateful functions like As a followup to that, we can also look for expressions of the form Can we do something that is similarly general that copes with expressions like |
I would love to have this in 2.0 but maybe it's too much to do on short notice. I think maybe the suggestions in my previous post are workable and could be done reasonably quickly. Thoughts? To add to the suggestion in my last paragraph, for dealing with things like
Steps (1) and (2) hold for arbitrary integer subexpressions, like |
The linear case |
I just thought of another potentially easier method. It's not as automatic or as general, but it would be easy to implement. As well as the user giving a condition |
Update from CNS meeting. We didn't agree on a syntax or a structure but we did agree that it would be good to have a way of providing code (in python/c++/etc. that would generate the synaptic connectivity). In Python this could be a generator function (with a yield statement), but with C++/Cython it would be a loop. |
I've been thinking about an implementation for some of these ideas and I think I've got something that will be doable in time for 2.0, isn't too complicated and allows it to be efficient (with a bit of user cooperation). First though, a quick review of some of the ideas: The general idea is to break down the condition into a disjunction
So this leads to the strategy I think would be doable for 2.0. Analyse the conditions. For each i, compute This covers a lot of cases, like A big thing that is missed by this but I don't think there's any way to solve the problem is Other things that would be nice for a more general system (post 2.0):
The way I anticipate implementing this is that we will just do some computations and pass additional variables to the template. This will be backwards compatible because templates are free to ignore this information and just use the condition directly. In addition, when we add the more detailed information in the future we can just further add additional variables and keep backwards compatibility again. |
A user could somewhat efficiently implement Again, this isn't quite as nice as it could be, but the point is that it allows users to make it efficient if we write a little guide to how it works. |
We did not quite follow the approach described here, but I think for all practical purposes everything mentioned here has been dealt with in #600. If something remains to do, let's open a new more specific issue. |
OK a thought on how to efficiently implement synapse creation. The problem to solve is that if you just compute
cond(i,j)
for all pairs (i, j) it isO(N^2)
and in many cases this is highly inefficient. We should list some of the cases and propose solutions.The two most important that I can think of are:
rand()<p
should be replaced with binomial distribution sampling, and also compounds likerand()<p and cond(i,j)
should be replaced by binomial distribution sampling followed by condition evaluation only on that subset.i==j
should be replaced with one-to-oneSo there are various possible solutions here - it would be nice to come up with something quite general that can adapt and become more efficient as we add special cases, but that doesn't require us to rewrite all the templates each time.
The most obvious implementation of
i==j
is just to explicitly detect it and convert it toconnect_one_to_one
and require that devices implement this connectivity function. Similarly forrand()<p
andconnect_random
. I don't really like this approach because it's not very general.Another option is to have a set of flags that are passed to codegen and the template can make use of that extra information. For example, if the condition was
rand()<p and f(i,j)
we could pass to codegensparseness=p
andcond=f(i,j)
. The code would then look something like:A more general and flexible mechanism would be to handle all conditions of the form
a and b and c
, parse them into a set[a, b, c]
, decode this set a bit and then pass that to codegen. For example,a
might berand()<p
,b
might beabs(i-j)<=width
andc
might bei!=j
. This would be parsed into:The parsed form is
(original_expr, specialisation_name, argument)
. The codegen template could then look through this list, check which ones it supported, implement them directly if they are supported and if not fall back on the default mechanism.It might be the case though that it's only worth doing one specialisation, because you won't improve the order of the computation by doing multiple specialisations assuming that each one returns an array of candidate indices. In fact, you might even slow it down. So another option is that each specialisation has an estimate of the number of candidate synapses j it will generate for any given i, and we simply choose the best one. For example if there was
rand()<0.5 and i==j
thenrand()<0.5
has an estimated0.5*_num_target_neurons
for each i, whereasi==j
has precisely 1, and in most cases1<0.5*_num_target_neurons
so this will be selected.Any thoughts on the above?
The text was updated successfully, but these errors were encountered: