I stumbled into a video via Google+ the other day, an informal discussion with Carl Hewitt explaining "The Actor Model (everything you wanted to know, but were afraid to ask)". This seemed a good opportunity to refresh my memory from when I looked in the late 80s, to catch up with any newer changes/additions, and to compare Actors with F-Nets. I also consulted the Wikipedia entry, and a paper which Dr. Hewitt recommended in the comments section. (I did not consult much of the more extensive written documentation, like Hewitt's and/or Agha's books, so I do not pretend to be fully up on all aspects of this work.)
The basis of the abstract model is that an actor, upon receiving a message, can do three things: Create more actors, send messages to actors it knows, and designate what it (the actor with this address) is to do with the next message it receives. And, from what I could ascertain, an actor knows the addresses of other actors it creates, as well as any addresses that it receives in messages, plus (presumably?) its own address.
From my own work, it seems clear what at least some of the intent is: Abstractly, to make immaterial the order in which the actor performs any/all of those activity components (creations, sends, and new behavior specifications). That's a worthwhile benefit, and leads to (some) separation of specification from implementation: Any implementation which does those same things in response to the same messages, regardless of the order or timing of those things relative to one another, is effectively equivalent in a system, and conversely, an actor can be considered as a function from the history of all the messages it has received so far to the set of new actors created and new messages sent as a result of the most recent message. (The "new behavior" component is not immediately observable: It just further defines that function -- i.e. the new actors and messages it should produce when given even more message history.) And because the actor's receipt of a message is essentially atomic, and the actor's behavior in response to that message is functional, that entire "receipt+sends+creations" collection can also be considered abstractly as one atomic action.
Those are nice attributes. But they pale in comparison to what ScalPL (and the F-Nets model upon which it is based) offers along similar lines. Perhaps that shouldn't be surprising: Actors predates ScalPL, and apparently even its ancestors. In ScalPL, an actor would correspond roughly to a plan, and a plan, in turn, is either a strategy or a tactic. For the remainder of this entry, I'll primarily limit my discussion to tactics.
A ScalPL tactic can be made to react to any number of specific resources becoming ready (e.g. containing "input"): There's no advantage to making that exactly one (like the actor model, considering the receipt of a message as being equivalent to a resource becoming available), but no harm in making it one, either. Like an actor, a tactic can also be specified as a function, but unlike an actor, not (generally) a function of the history of messages it has received; instead, a function of the data ("input messages" in actor-speak) it's observing right now, specifying the results ("output messages") it will produce right now as a response. In other words, it's pretty much just your normal everyday function, with no hidden state. In fact, the data a tactic observes (i.e. its inputs) and that it produces (its outputs) can be (all or part) on the very same resources (think "variables" or "files"), so the specification of an input-to-output transformation for a particular resource can just be a specification of the changes (i.e. updates) that need to be performed to the contents of that resource. That should look very familiar: It's the way ordinary imperative programs generally deal with memory, observing (reading) and updating (writing) all or part of it in place, instead of sending messages around from place to place. (The semantics of inter-tactic communication in ScalPL/F-Nets is carefully designed to be easily and efficiently implementable as messages, too, if the situation calls for it, but that is a detail generally unimportant to the planner/programmer.)
Of course, if one wants to make a tactic with behavior that (like an actor) depends upon its history as well as its new/current input(s), it's easy to do: Just consider/use one or more resources as the salient parts of its history, and have the tactic observe and update those resources as it does others containing inputs and outputs. (No, it would not really be equivalent to restricting actors to also be functional, and just constantly sending their history back to themselves in messages: Actor messages have different, heavier semantics than ScalPL resource updates.)
To bring this home, consider you have a person (or even a robot), and you know that its behavior in response to its environment at any one time is a combination of its nature (how it was built) and nurture (everything that's ever happened to it in the past). Even if you know how it began (i.e its nature), and what its current environment is like, unless you also know its nurture (entire history), you have little idea how it will currently respond to its environment. That's the actor case -- or, for that matter, most imperative programming in general, as I hope to address later. In the tactic case, its nature does not change and there is no nurture component: If you know what the tactic was (and therefore still is), and what its environment is, you know how it will behave. There's no hidden state (e.g. history), it's very WYSIWYG (What You See Is What You Get).
As for creating other tactics (the way an actor creates other actors): A ScalPL tactic does not create other tactics first-hand, for some of the same WYSIWYG reasons that tactics don't depend on history. That is, all relationships in ScalPL are intended to be illustrated/visualized/specified in its visual representation, rather than hidden inside of one or more tactics. So if a tactic is meant to become active at some point, it and its (eventual) relationship to other tactics and resources is specified (graphically) from the beginning. The effect of creating (activating) a tactic results (again, in a clear diagrammatic fashion) from another tactic altering a resource they have in common, thereby awakening the until-then quiescent tactic. (It the potential relationships aren't known from the beginning, there are ways to create those relationships, too, within strategies, just as there are ways to hide history within one, but that's for another post.)
I can (and probably will) discuss the Actors video further in this blog, but the main thing I hope you get from this specific post is that ScalPL incorporates a WYSIWYG approach to (a) how a plan will behave now in response to its current environment, (b) where it might get its inputs from, (c) where its results might be felt, and (d) what other plans might be activated as a result. Unlike Actors, ScalPL does not hide information like the above within a the tactic (e.g. in terms of its accumulated state over history, including the addresses that it knows or uses), is not limited to a message model, and it is not limited to one input per tactic activation.
Methods for engineering correct, portable, performant, scalable software for concurrent environments (HPC, multicore, cloud, grid, distributed)
Friday, October 19, 2012
Tuesday, October 16, 2012
Video summary of the Scalable Planning book (intro chapter)
A 13-minute description of the book (summarizing the first chapter).
From near the end...
"The Scalable Planning book isn't your typical parallel programming textbook, but it is built with that use in mind. If you don't know anything about programming, that's OK: It introduces all terminology, and avoids too much lingo. But if you are using it to teach or to self-learn parallel programming, you should ask yourself: Should concurrency concepts be taught the same way they were 30 years ago? Programming curricula these days rarely start with machine language and assembler: Should today's parallel programming curricula be saddled with their analogs, message passing, semaphores, and locking? Here, my answers are no: There are chapters to cover the lower-level mechanisms if you want to go there, but the focus here is on higher-level concepts, on constructing correct, portable, understandable, efficient programs (plans), leaving the low-level details to others. As a result, it is organized much like other sequential programming texts, with chapters on topics like structured programming, object-oriented principles, arrays and dynamic resource allocation, and formal methods, but in a concurrent context."
From near the end...
"The Scalable Planning book isn't your typical parallel programming textbook, but it is built with that use in mind. If you don't know anything about programming, that's OK: It introduces all terminology, and avoids too much lingo. But if you are using it to teach or to self-learn parallel programming, you should ask yourself: Should concurrency concepts be taught the same way they were 30 years ago? Programming curricula these days rarely start with machine language and assembler: Should today's parallel programming curricula be saddled with their analogs, message passing, semaphores, and locking? Here, my answers are no: There are chapters to cover the lower-level mechanisms if you want to go there, but the focus here is on higher-level concepts, on constructing correct, portable, understandable, efficient programs (plans), leaving the low-level details to others. As a result, it is organized much like other sequential programming texts, with chapters on topics like structured programming, object-oriented principles, arrays and dynamic resource allocation, and formal methods, but in a concurrent context."
Subscribe to:
Posts (Atom)