cloud-fan commented on code in PR #57092:
URL: https://github.com/apache/spark/pull/57092#discussion_r3584580721


##########
PIPELINED_SHUFFLE_DEPENDENCY_SPEC.md:
##########
@@ -0,0 +1,386 @@
+# Pipelined Shuffle Dependency & Concurrent Stage Scheduling
+
+A spec for running data-dependent stages of a single job concurrently, 
connected by a shuffle the
+consumer reads incrementally.
+
+---
+
+## 1. Motivation
+
+Today, when two stages of a job are connected by a shuffle, they run one after 
another: the consumer
+stage does not start until the producer's shuffle output is fully 
materialized. (Independent stages —
+ones not connected by a shuffle — already run concurrently.) Some workloads 
need even
+shuffle-connected stages to run **concurrently**, with the consumer reading 
the producer's output
+**as it is produced** rather than after the producer finishes. This spec 
introduces the scheduler
+primitives to express and run that.
+
+"Run these stages concurrently" and "the connecting shuffle is incremental" 
are the same decision
+seen from two sides: co-scheduling a producer and consumer is only useful if 
the edge is readable
+before the producer completes.
+
+---
+
+## 2. Primitives
+
+### 2.1 Pipelined shuffle dependency (PSD)
+
+A shuffle dependency declared **incrementally readable**: a consumer stage may 
begin reading its
+output while the producer stage is still running.
+
+- It is a shuffle dependency (has a `shuffleId`, partitioner, map/reduce 
sides); the *pipelined*
+  property is a binding part of the scheduler contract, not an advisory hint. 
("Pipelined",
+  "incremental", and "transient" all describe this same edge in this doc — 
read as its output being
+  streamed to the consumer as produced, not stored.)
+- The property is set during **physical planning** (an execution concern, not 
a logical-plan one)
+  and carried into the `ShuffleDependency` the `DAGScheduler` reads at 
stage-creation time.
+- It is also the **per-dependency selector** for the shuffle implementation: 
the shuffle layer maps a
+  pipelined dependency to an incremental `ShuffleManager` and everything else 
to the default, so one
+  job with both regular and pipelined groups uses the right implementation for 
each. The scheduler
+  construct stays generic; the shuffle implementation stays pluggable.
+  - For example, an additional conf (e.g. `spark.shuffle.manager.incremental`) 
can be introduced to
+    specify the incremental shuffle implementation used for pipelined shuffle 
dependencies, alongside
+    the existing `spark.shuffle.manager` for the default.
+
+A **regular shuffle dependency (RSD)** is an ordinary shuffle dependency: its 
output must be fully
+materialized before any consumer reads it.
+
+Note: the name *pipelined* is deliberately chosen over *streaming*. The 
property is that a consumer
+reads producer output as it is produced — software-pipelining of dependent 
stages — a general
+execution capability. Streaming / real-time mode (RTM) is the first caller, 
but nothing about the
+primitive is streaming-specific.
+
+### 2.2 Pipelined group (PG)
+
+The set of stages connected to one another through pipelined edges — the 
connected component of the
+stage DAG when only pipelined edges are considered.
+
+- A stage with no incident pipelined edge is a **singleton group** and behaves 
exactly as a normal

Review Comment:
   Option 3 (dynamic recomputation) is the one I'd take — it's the best 
resolution of this thread, and it's better than my original `SchedulingUnit` 
proposal because it *removes* the awkward construct instead of wrapping it.
   
   The thing worth being explicit about: option 3 changes how we should 
*describe* this in the spec, because it retires `SchedulingUnit` as a logical 
concept, not just as an implementation. `SchedulingUnit` existed to give the 
lone stage and the group a common supertype so the size>=2 discrimination 
happened once, structurally — but option 3's whole thesis is that `Stage` stays 
the single scheduling primitive and group-ness is a *derived predicate over the 
immutable stage graph* (`isPipelinedGroupMember`, `pipelinedGroupOf`, 
recomputed on demand). There's no supertype to name and no `SingleStageUnit` 
wrapper. Putting `SchedulingUnit` in the spec would just recreate the same 
spec-vs-code friction from the other side.
   
   So the clean framing isn't "abstract over the singleton" — it's "eliminate 
it": a pipelined group has >=2 members by construction (it's a connected 
component over edges, and an edge has two endpoints), and a stage with no 
pipelined edge simply *isn't in a group* — it keeps the existing per-stage 
behavior because it's a non-member, not because it's "exempted." The §4/§5/§6 
re-exemptions then dissolve on their own.
   
   Two spec edits follow from this and are worth doing in the same pass, since 
they currently assert the *stored*-membership model option 3 replaces:
   - §2.2: drop the "singleton group" construct — state the >=2 invariant and 
that a non-member is an ordinary stage.
   - §3: "Every stage belongs to exactly one group (singletons included). Group 
membership is fixed at stage-creation time." — both halves go wrong under 
option 3. A non-member belongs to *no* group, and membership isn't *stored* at 
creation; it's *derived from the graph wherever a decision needs it*, stable 
only because the graph is immutable. I'd reword to something like: "group 
membership is a function of the pipelined-edge structure of the stage graph, 
recomputed on demand; it is stable because that graph does not change after 
creation."
   
   One caveat on the "no persistent state, correct-by-construction" claim for 
option 3: the `HashMap[Stage, DeferredCompletion]` buffer *is* persistent state 
that still needs teardown on abort/job-cancel, so option 3 narrows the 
lifecycle surface rather than eliminating it — the deferral buffer is the one 
piece that can still go stale. Worth stating that explicitly so the "nothing to 
keep consistent" framing isn't overclaimed. But group *extent* being derived is 
a real win, and it's the right call.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to