Scheduling threads like Thomas Jefferson
stevana.github.io
stevana.github.io
Maybe, if the processes at each stage are I/O-bound, then it might make sense. But if they are CPU-bound, then I am not sure this way of pipelining helps - you're moving data between different CPUs, destroying cache locality.
However, the cache locality thing is complicated. Each bottle has data associated with it, but each processing stage might also have data. For example, maybe a particular stage uses a lookup table. Or maybe stages keep statistics as they process bottles.
If you have one CPU doing all the work for a particular stage, then per-stage data stays in its cache. But if you have one CPU doing all the work for a particular bottle, then all the per-bottle data stays in its cache. So there's a trade-off that depends on the specifics.
Who here hasn’t bought themselves some time from vertically or horizontally scaling a database by hoisting a bunch of calculations up and out of the transaction? Do them before or after the constraint.
The farther you have to reach to coordinate use of the constraint the better it might be to hand the inputs to the constraint and let an experts handle things.
- if the actual performance deviates from the predicted (scored) performance, the system easily enters a degenerate bottlenecked state.
- and if that happens, the many internal queues make diagnosis, root causing, and confidence in a fix all exponentially worse.
Now you might assert that this will be applied in situations where scores are accurate and brown failures do not occur. Those aren’t the situations I deal with.
But we’ve generally found it works better for the worker to pull when its queue is empty, and of course if you have partially ordered events nobody can process (start or reject) those ordered tasks until the borked one finishes or times out.
So the situation you describe can absolutely happen, but is not a given. It’ll depend on other decisions.
Sounds like the author of this would be interested in Queueing Theory[1] (in the sense of being interested in mathematical formalisms to explore this stuff). Apportionment[2] is also studied as a very specific thing unto itself.
There's a huge mass of published research "out there" dealing with queueing and scheduling. Not all of it pertains to "thread scheduling" but there's quite a bit of conceptual overlap between something like thread scheduling and job floor scheduling. And some of the stuff on apportionment likewise probably relates at least by analogy.
[1]: https://en.wikipedia.org/wiki/Queueing_theory
[2]: https://en.wikipedia.org/wiki/Mathematics_of_apportionment
That's why in the vast majority of circumstances you'll be running many things on many CPUs, you just throw all the work at the CPUs and let the chips fall where they may. Deliberate scheduling is a tool, but an unusual one, especially as many times the correct solution to tight scheduling situations is to throw more resources at it anyhow. (Trying to eke out wins by changing your scheduling implies that you're also in a situation where slight increases in workloads will back the entire system up no matter what you do.)
... and if you aren't, then clearly, by the way "if-then" statements work, the "then" clause doesn't apply.
Pipelines are strictly processing stages where the 'production of the input' and processing on the inputs are not synchronized. For example, one sends n requests to via a pipeline protocol to a remote server without waiting for acks for each input from the server. There may only be one such processing pipeline (and thus no parallelism) while there is pipelining.
But, I would consider pipelining to be a form or parallelism. It breaks up a task so that parts of it can be run simultaneously (in different stages of the pipeline, simultaneously). There are other ways to do parallelism of course, but it is a way.
In your example, if there are multiple pipeline stages in this server, then the tasks should be worked on simultaneously, and so parallelism is occurring.
Multi-core, SIMD, and pipelining. Parallelism has multiple dimensions.
To make it faster, you either have to decrease the time for a step (but you will always be capped with the slowest step), or go for parallelism---a separate pipeline (or pipelines). For example, with one pipeline, each step taking 1 unit of time, once the pipeline is filled, will take six units of time to make a six-pack (the first will take longer due to the latency in filling the pipeline). You can make five other pipelines, and then get a six-pack per unit of time (again, after filling all the pipelines).
A single pipeline just makes the output have a predictable latency and time; multiple pipelines give you parallelism.
Compared to 18 units of time needed to make a six-pack without pipelining. Gee, what a wondrous invention this "pipeline" is: having three workers means the work is accomplished thrice as fast, yet there is (according to you) no parallelism at all! So naturally, if we could introduce parallelism inside this single pipeline, we would be able to make another triple reduction in time, and get a production of six-pack take only 2 units of time.
> A single pipeline just makes the output have a predictable latency and time; multiple pipelines give you parallelism.
No, the pipeline does give you parallelism because you're doing three (in the bottling example) pieces of work simultaneously, that is: in parallel. Filling, capping, labeling are each being done on different bottles at the same time. How is that not parallelism?
Let's use some numbers:
Filling, capping, labeling take 30s, 15s, 15s each (arbitrary, chosen for easy math). Without a pipeline you will process 60 bottles per hour (say one station that does all 3 tasks and then kicks out the bottle, let's ignore transition times). With a pipeline you can get 120 per hour. You've improved throughput. The latency per bottle is still 60s.
BTW, you can double throughput again without even needing a full second pipeline just by adding a second filling station (with my example numbers) and feeding filled bottles to the same capping and labeling stages, getting you to 240 per hour.
> Yes, once the pipeline is filled up, you have the three operations going on at the same time, but it's still a sequence of steps that need to be performed in order for any given bottle.
as not parallel.
It seems to me that what you are calling parallelism, most people would instead call homogeneous parallelism. Which is a subset of parallelism.
But that’s new equipment, so filling the bottle is still the slow step in some past version of the bottling plant. You’re still going to fill three, four, six bottles at a time, then cap them, but the labeling machine might just be serial.
The way those machines work is also pipelined - add some space between the bottles, slap a label on, use rollers to make the label stick.
Then you load the cases n bottles at a time, not via pick and pull.
Several of those steps could feed in from one machine to four and back to two and then to one.
More equipment means more maintenance but also affords you taking part of the system offline and still keeping output from cratering.
https://en.wikipedia.org/wiki/Instruction_pipelining
Your argument basically amounts to forming an arbitrary definition of "unit" that consists of the whole thing so that then you can state that there is no parallelism. By that token, an 8-core processor has no parallelism because it can only execute a single package of 8 threads at any given time.
And to pick a nit, there is always some synchronization between the submission of an input and the processing of that input: the submission must happen before the processing, unfortunately.