Live data from Hacker News

Ask HN: On Rob Pike's Concurrency is not Parallelism?

news.ycombinator.com

11–20 of 71 posts

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#11
post #7
post #4

Parallelism is when you run your program on multiple processors. Semantics of your program does not change whether you run it on single processor or multiple processors. Concurrency is when you write your program using multiple threads. Your program looks and means vastly different if you use threads. You use concurrency not for performance gain, but for clarity of your program. You use parallelism for performance ga…

That can't be right. Threads don't improve the clarity of most programs; they're notoriously unclear.

I agree with you, but not in the way you intended. I suspect that most programming language implementations of concurrency are bolt-ons and are a bit broken in terms of their human (programmer) interface design.

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#12
Concurrency is more than decomposition, and more subtle than "different pieces running simultaneously." It's actually about causality.

Two operations are concurrent if they have no causal dependency between them.

That's it, really. f(a) and g(b) are concurrent so long as a does not depend on g and b does not depend on f. If you've seen special relativity before, think of "concurrency" as meaning "spacelike"--events which can share no information with each other save a common past.

The concurrency invariant allows a compiler/interpreter/cpu/etc to make certain transformations of a program. For instance, it can take code like

    x = f(a)
    y = g(b)
and generate

    y = g(b)
    x = f(a)
... perhaps because b becomes available before a does. Both programs will produce identical functional results. Side effects like IO and queue operations could strictly speaking be said to violate concurrency, but in practice these kinds of reorderings are considered to be acceptable. Some compilers can use concurrency invariants to parallelize operations on a single chip by taking advantage of, say, SIMD instructions or vector operations:

    PIPELINE1  PIPELINE2
    x = f(a)   y = g(b)
Or more often:

    [x1, x2, x3, x4] = [f(a1), f(a2), f(a3), f(a4)]
where f could be something like "multiply by 2".

Concurrency allows for cooperative-multitasking optimizations. Unix processes are typically concurrent with each other, allowing the kernel to schedule them freely on the CPU. It also allows thread, CPU, and machine-level parallelism: executing non-dependent instructions in multiple places at the same wall-clock time.

      CPU1        CPU2
    x = f(a)    y = g(b)
In practice, languages provide a range of constructs for implicit and explicit concurrency (with the aim of parallelism), ranging from compiler optimizations that turn for loops into vector instructions, push matrix operations onto the GPU and so on; to things like Thread.new, Erlang processes, coroutines, futures, agents, actors, distributed mapreduce, etc. Many times the language and kernel cooperate to give you different kinds of parallelism for the same logical concurrency: say, executing four threads out of 16 simultaneously because that's how many CPUs you have.

What does this mean in practice? It means that the fewer causal dependencies between parts of your program, the more freely you, the library, the language, and the CPU can rearrange instructions to improve throughput, latency, etc. If you build your program out of small components that have well-described inputs and outputs, control the use of mutable shared variables, and use the right synchronization primitives for the job (shared memory, compare-and-set, concurrent collections, message queues, STM, etc.), your code can go faster.

Hope this helps. :)

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#14
post #9
post #2

I believe the concept says to focus more on task-based parallelism rather than data-based parallelism. In Go, it is easy to create multiple tasks/workers each with a different job. This is implicitly parallelizable - each task can (but doesn't have to) work within their own thread. The only time when the workers can't run in parallel is when they are waiting on communication from another worker or outside process. Th…

I don't agree with that; task parallelism is easier than data parallelism in an actor/CSP-based system, but both have their place. Take something like x264 -- task parallelism will not help it, unless you're encoding multiple videos at one time. But data parallelism (SIMD, in particular) is the reason it's the fastest encoder around.

x264 gets equal use from threads per-frame as it does SIMD per-pixel. There's a pretty much linear speed increase for each new thread, even.

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#15

I thought he was just giving an excuse for the abysmal multi-core scaling of idiomatic Go programs.

Go scales quite well across multiple cores iff you decompose the problem in a way that's amenable to Go's strategy. Same with Erlang.

No one is making "excuses". It's important to understand these problems. Not understanding concurrency, parallelism, their relationship, and Amdahl's Law is what has Node.js in such trouble right now.

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#16
post #9
post #2

I believe the concept says to focus more on task-based parallelism rather than data-based parallelism. In Go, it is easy to create multiple tasks/workers each with a different job. This is implicitly parallelizable - each task can (but doesn't have to) work within their own thread. The only time when the workers can't run in parallel is when they are waiting on communication from another worker or outside process. Th…

I don't agree with that; task parallelism is easier than data parallelism in an actor/CSP-based system, but both have their place. Take something like x264 -- task parallelism will not help it, unless you're encoding multiple videos at one time. But data parallelism (SIMD, in particular) is the reason it's the fastest encoder around.

In general, task paralellism can model anything data parallelism can and given "a sufficiently smart compiler" you can end up with the same result. This is an informal corollary of Needham's Duality (which is itself informal, so make of it what you will).

Our current hardware tends to offer great data parallelism for homogenous task queues and task parallelism for heterogenous task queues. Given that, we task parallelism needs a lot more consideration from a human. It's also the case that our current implementations of data parallelism tend to focus on shared memory computations, so their scope is a lot more limited than the distributed-system-conflated discipline of task-oriented concurrency, where we're currently having an explosion of engineering.

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#17
post #4

Parallelism is when you run your program on multiple processors. Semantics of your program does not change whether you run it on single processor or multiple processors. Concurrency is when you write your program using multiple threads. Your program looks and means vastly different if you use threads. You use concurrency not for performance gain, but for clarity of your program. You use parallelism for performance ga…

Also, concurrency provides some performance gains that are not related to parallelism, such as efficient use of the CPU while waiting on I/O.

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#18
Take a look at lthread:

https://github.com/halayli/lthread

lthread supports concurrency and parallelism using pthreads. Each lthread scheduler runs its own lthreads concurrently, or better said, one at a time. But from an observer's perspective they look like they are running in parallel.

Now if you create 2 pthreads on a 2 core machine and each runs an lthread scheduler then you have true parallelism because you can have 2 lthreads running in parallel at the same time. One by each scheduler.

I feel this is a closer context to what Rob is discussing than what I found in the comments here.

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#19
Obviously both terms get used in a variety of overlapping ways. Without looking at how the terms are used in the slides you refer to, I think the proper definitions are:

Concurrency is a property of a program's semantics, usually seen in a 'thread' abstraction. The most important part of concurrency is nondeterminism. Concurrency might permit parallelism depending on hardware, language runtime, OS, etc.

Parallelism is a property of program execution and means multiple operations happening at once, in order to speed up execution. A program written to take advantage of parallelism can be deterministic, but often is accomplished by way of concurrency in OS threads. Because most languages still suck.

Re: Ask HN: On Rob Pike's Concurrency is not Parallelism?

#20

I thought he was just giving an excuse for the abysmal multi-core scaling of idiomatic Go programs.

Go scales quite well across multiple cores iff you decompose the problem in a way that's amenable to Go's strategy. Same with Erlang. No one is making "excuses". It's important to understand these problems. Not understanding concurrency, parallelism, their relationship, and Amdahl's Law is what has Node.js in such trouble right now.

Trouble? Node.js has linear speedup over multiple cores for web servers. See http://nodejs.org/docs/v0.8.4/api/cluster.html for more info.
Post reply on HN