That battle has unfortunately been lost and different sources give different definitions, often exactly swapped. This was discussed in one of the HN posts linked in the article: https://news.ycombinator.com/item?id=36318280
In the end I don't think it is too much of an issue. What confusion is really brought by conflating parallelism and concurrency? Sure, concurrent programs can be serialized onto a single core (that's how deterministic simulation testing implementations like Antithesis and record & replay implementations like Mozilla's rr operate). But there isn't some deep conceptual unlock you get by having a strict conceptual boundary between concurrency and parallelism.
It's really important to get people to recognize that concurrency can happen on a single core or a single task-switching thread. You don't necessarily need to split off parallelism to explain that, but it helps.
And it's worth talking about how you can have a single task run in a parallel way, for varying strictness of 'single'.
Coroutines and SIMD are far enough apart that their execution models should have different words.
I think there is a deep conceptual unlock: concurrency is about semantics, whilst parallelism is an operational property. I use this distinction a lot in my own work. Concurrent programming primitives are inherently non-deterministic (and usually about handling non-deterministic events), on top of which we must then establish some kind of properties (sometimes determinism to some extent). Many interesting parallel operations are however completely deterministic, and the fact that they are parallel is a property of their assigned cost model (and hopefully implementation, in practice).
I agree that this distinction is hardly universal, but it seems to be growing increasingly established, and I think it is worth fighting for it.
I don't like the essential characteristic of concurrency being nondeterminism. its really that multiple processes are running concurrently. if we don't have serializing operations, we have arbitrary execution order. but if we do then we can introduce the necessary determinism while still being (largely) concurrent in evaluation. and if those logically concurrent processes are physically concurrent then we have parallelism. so the first is necessary but not sufficient for the latter.
so I find saying that we have one or the other to pretty misleading.
deterministic scheduling is possible, but most theoretical concurrency models assume non-determinism.
And even with deterministic scheduling, concurrency might be dictated by external stimuli (for example request arrival) that are not deterministic.
Personally I think it's not a good idea to think too rigidly about and try to draw a huge distinction between the two. They're on a continuum and sometimes I'd say some things aren't even strictly speaking "between" them either. Sitting down and trying to classify code into "parallel" and "concurrent" is as likely to do harm as to do any good.
I firmly disagree, they are not a continuum, they are binary properties of what they describe. Code can have concurrency primitives, but parallelism primitives must necessarily come from the environment the code executes in, whether it's multiple code streams on a multicore processor or process parallelism provided by an operating system. Programs that are parallel are necessarily also concurrent (if they must communicate between parallel executions), but the inverse is not necessarily true.
If this distinction wasn't important, Python's infamous GIL would not be an issue.