From what I understand here, concurrency is combined being combined with
parallelism. Some systems do not combine these models. I generally view concurrency as operations occuring at the same time that aren't related and don't necessarily rely on each other, where as parallelism is where you can cut up a problem into sequences which can be run concurrently and then combined.
I really want to emphasize that concurrency and parallelism are quite different and that often it depends on the problem which kind of concurrency or parallelism best maps to the problem. As well it often depends on the problem which kind of concurrency or parallelism provides the best performance.
One example I have is that the ocaml bytecode vm handles its own threads, while the native ocaml binaries were using pthreads. I was able to have 10000+ vm threads which all were relatively quiet, while I could only have about 1000 pthreads.
I think some of the patterns Doug mentions are valuable but they aren't applicable to everything. Remember programming is also about representing the problem for the programmer, the computer and the stakeholder who might use or need the code. If we enforce a certain styles we can get in the way of people representing their problems.
I haven't really said anything other than some problems are better suited to different models of concurrency or parallelism than others. Different models give you different performance and on different operating systems and VMs will have different advantages and disadvantages.
This doesn't even touch distributed concurrency and parallelism. If you try out MPI you will see where the "shared memory" approach starts to fall apart as the latency of your links increases and the max throughoutput decreases.
Summary: There is no easy way out
abram
On Wed, 15 Apr 2009, Paul Tarvydas wrote:
On Wednesday 15 April 2009 10:26:26 am Vishvajit Singh wrote:
Ouch.. 89 threads?
I was confused about agents, apparently.. it seems that:
send -> runs on the thread pool send-off -> creates a new thread
Mea culpa :)
Not so fast :-).
I just finished watching the concurrency screencast, but the exact answer isn't in there.
Here is what I think he might be saying:
A classical (preemptive) process requires that you carve out a piece of memory for the stack and the context for the process. If you have 300 processes, then you have 300 stacks. If you have only one CPU, then 299 of the stacks are idly wasting space. (This is one of the reasons why people resort to uglyosities such as thread pools).
In VF and stackless programming (and maybe in Clojure, given the statement about millions of agents in memory), there is only one stack - the hardware stack.
In VF, each instance of a part uses up only enough memory for two queues (due to VF semantics) and a flag[+]. VF parts - basically state machines - run each action to completion. Parts all share the same stack and they leave no stacked context lying around "for next time".
To run a set of parts, you need a thread of execution. The thread of execution winds its way through all of the activated parts and then dies out when there's no work left to perform.
On bare hardware, the thread of execution is provided by a hardware interrupt (if the hardware supports prioritized interrupts, you can have more than one thread of execution stacked up).
On an O/S, a thread of execution is whatever you want it to be, e.g. a user process or a thread.
If you wanted to spray the threads of execution across a bunch of CPU's, you would have to have at least one thread of execution on each of the CPU's.
I wonder if this is what Hickey is getting at? The JVM will schedule threads onto various CPU's. In the concurrency screencast, he uses a dual core machine and shows that his simulation is using more than 100% of the CPU (i.e. more than one core is active).
His ant simulation could benefit from the addition of CPU's, up to 89 of them.
He stresses (repeatedly) that there is no explicit locking in the user-written code. He stresses that the GUI would be extremely hard / wasteful to write using locks. The GUI takes a snapshot in time of the 80x80 world and then renders this snapshot on the screen. According to him, it never gets it wrong - there are always the correct number of ants on the screen, they never overlap, etc.
pt
[+] Plus any static state variables declared by the programmer.