I’ve never used the actor model in any complicated project. I’ve also never really used NupPIC, So I don’t know really anything about what I’m talking about but…
It seems to me that the brain computes concurrently (because it’s physically concurrent), and NuPIC is meant to model the brain, so my question is, “should NuPIC, or a network of NuPIC engines be implemented in the Actor model of programming?”
Actors could be regions, or if actors are cheaper, they could actually model individual cortical columns.
Connections are messages so their cheap and easy to set up and tear down. modeling connections would be straightforward. it would be easily scalable across many cores or many computers.
It just seems like the way to go intuitively, perhaps using elixir or erlang so concurrency is easy, parallelism is natural and shared state isn’t possible.
@jordan.kay thanks for the convergent thought! That’s my intuition too. You’re welcome to participate in the Pony experiment! Once the pattern is validated, one can either switch to Elixir and re-implement, or scale out of one machine via whatever messaging technology in Pony, e.g. Msgpack via ZeroMq.
As in all nature (like the algorithm of evolution for example) its parallel.
There’s no central processing unit. The hardware is parallel. There’s a bunch of stuff happening all over the place at the exact same time. Some of that stuff ends up having a larger influence for a time by inhibiting other stuff.
Ok the reason why I’m asking is besides curiousity and Im lazy to look up the relevant Neuroscience background, is that if you wanna be exact you might need to differentiate parallelism and interleaved concurrency in your implementation and make sure to determine which of the two is done really by the brain. The two concurrency implementations are both concurrent but their behavior is not the same. If the brain’s operations depend too much on concurrency, which I believe it does, then concurrency must also be simulated properly.
@Jose_Cueto back to the Actor Model: it conveniently unifies concurrency, parallelism and distribution. As HTM is not a “whole brain simulation”, there will be practical trade-offs in the mapping of the biology to the software running on current general purpose hardware.
What would be the primary benefit of partially simulating concurrency in HTM, and its advantage over no concurrency?
I like this idea but I think that introducing concurrency in a system also introduces complexity, and IMO it’s good to have its complexity cost be lesser than the benefits it brings. On the other hand, if at some point a math/science model of HTM is established, it will be then be difficult to use this in a concurrent HTM simulation because its steps will have an unpredictable order. Then we will have a problem similar to DL where people just don’t know why the networks work.
My 2 cents, I’d apply concurrency in the components such as the SP and TM as microservices not for the purpose of simulating the brain but for allowing ease of integration between these components in a production environment, thus they’ll be treated as ordinary applications. One could then run an SP as an app that can be attached with an HTM region/memory.
Elixir. This is actually what I’m kicking around for the next couple of days… the appeal of it to me (as opposed to Pony, which is a pretty neat language) is the built-in distribution of threads across multiple nodes (which could be Pi’s…see Nerves). Nothing terribly shareable yet, but the basic GIST is:
Central DB – acts as the “skull”, where columns coming into and out of existence register themselves to the group (using mnesia)
The basic unit of organization is a spatial pool. On startup, the pool (taking a seed:id pair) initializes itself, number of columns, random initialized connections and the strengths of those connections into an input space, then starts waiting to input (either directly from its own input space, or perhaps randomly peeking in on other pools in the group if it isn’t busy itself).
Pseudo-lisp style
(
pool (
column1(inputspace(encoder(input))))
column2(inputspace(encoder(input))))
column3(inputspace(encoder(input))))
)
And Elixir gist:
def column(raw_input, column_id) when is_float(raw_input) do
|> encoder(raw_input)
|> column_connections(column_id)
end
def setup_pool(:num_cols, :layer_per_column, _opts) do #set it up
end
…
I need to see it, but I suspect that the distributed nature of this, running on different varieties of hardware, would naturally lead to differences in timing. Because race conditions don’t really matter (where some nodes might be faster for a time-step and others slower, depending on load and variations in processing speed), a distributed system might naturally self-inhibit, and we wouldn’t care about the variations in timing, and instead aim for having “a thousand brains”, which could have different columns across different HTMs voting on various input predictions. Network latency might even be a feature, rather than an issue.
Ditto. One of my reasons for going in this direction using Elixir. Working to provide a better example, then will likely create a new thread where I share github/updates on progress.
I’m trying out Pony to see if performance could be improved on one machine (as Pony is a LLVM-compiled language). Actor Model implementations are translatable into one another nicely. Although, it’s a larger task, one could implement an Erlang node in Pony and network it via the same mechanism with the Elixir implementation as Elixir one. On the other hand, one could also use something more universal, e.g. MsgPack via ZeroMQ/Websockets/etc… between any implementation.
There is no conceptual difference between an actor and a single-threaded microservice that responds to requests seqentially
The Actor Model is not a Task or Thread based concurrency. I’d recommend to look at it in more detail.
The proposal to extract parts as Microservices is introduction of complexity too: timeouts, reconnects, security, service discovery and others. So, it is a set of trade-offs too.
the physical world has lots of uncertainty and is practically predictable only in statistical sense. Distribution adds even more uncertainty than concurrency on a single machine.
A nice property of the Pony scheduler is causal messaging in the whole run-time. In Erlang/Elixir this holds between a pair of processes, which is also quite good.
This is harder to state for, say HTTP or other TCP/UDP messaging, as packets may arrive out of order. Which is still practical, just gives even less guarantees.
I was only pointing out that these components are IMO the simplest to apply concurrency with and the benefits are easily determined, for example, I could run an SP independent from any region/memory or HTM algorithm in a production environment, I having nothing against the Actor model.
Again not about the Actor model or its implementation detail but I can assure though that whatever language/model we use, that at least in *nix processor instructions are either interleaved in one processor core or run simultaneously. But this is not important for this context.
Re: microservice. Yes it will definitely add complexity but this does not promise to simulate the brain’s concurrency behavior.
Sorry if I have brought any confusion, good work by the way! My whole point is simply that simulating concurrency in the brain IMO may be a “make or break” aspect, IOW if in the future Neuroscience tells us that concurrency in the brain is “first class operation” just like spatial and temporal algorithms are treated, then we might break something or introduce more complexity. Don’t like to sound pessimistic sorry.
thanks for the answer! I’m optimistic regarding this point, as demonstrating that the brain is neither concurrent nor parallel seems a much harder thing to do. Cells are physically parallel, thus neurons are physically parallel. As @jordan.kay has pointed out, if the brain were not to be concurrent, one would have to demonstrate a global synchronization / sequencing mechanism, which is (to my view) not possible due to the possibility of splitting the brain into two (sort of CAP theorem for the brain)
No need to be dogmatic about the micro services definition. The main this is just that it works first. The spatial pooler has to keep some state about the columns; Erlang/Elixir have either the ETS or mnesia to hold and call upon that, which can either be passed as a message from parents to children, or the pool parents can pass column IDs which threads can then use to lookup column state (haven’t settled yet).
@jordan.kay if you’re interested, I’ve made a little experiment on “dumb” neurons voting, where each is modeled as an Erlang/Elixir process: https://github.com/d-led/elixir_ne just to play around with the time domain and the BEAM scheduler.