Skip to content

[WIP][VL] Support setting stage execution mode#12511

Open
marin-ma wants to merge 5 commits into
apache:mainfrom
marin-ma:add-stage-execution-mode
Open

[WIP][VL] Support setting stage execution mode#12511
marin-ma wants to merge 5 commits into
apache:mainfrom
marin-ma:add-stage-execution-mode

Conversation

@marin-ma

Copy link
Copy Markdown
Contributor

Background

When GPU execution is enabled, a Spark stage can run entirely on the GPU only when every operator in that stage supports cuDF. If any operator falls back, the whole stage must use the CPU execution path.

However, the mapper and reducer sides of a shuffle are separate stages and may use different execution modes. For example:

  • A scan stage may fall back and execute with the CPU pipeline.
  • A downstream join stage may still be fully supported by cuDF and execute with the GPU pipeline.

Previously, this CPU-to-GPU transition could fail. The ColumnarShuffleExchangeExec was configured based on the mapper-side plan and was not marked for GPU execution when the scan stage fell back. The downstream reducer stage could nevertheless require the GPU shuffle reader, resulting in inconsistent shuffle execution modes.

Changes

This PR introduces explicit execution modes for Spark stages and determines the mapper and reducer modes independently at each shuffle boundary.

For the example above:

  • The scan stages are marked as CPUStageMode and use the CPU pipeline and CPU shuffle writer.
  • The downstream join stage is marked as GPUStageMode and uses the GPU shuffle reader and GPU pipeline.

The selected execution modes are propagated through the shuffle exchange so that the shuffle writer, shuffle reader, and batch-resizing logic use the correct implementation for their respective stages.

Copilot AI review requested due to automatic review settings July 14, 2026 17:15
@github-actions github-actions Bot added CORE works for Gluten Core VELOX labels Jul 14, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an explicit stage execution mode concept (CPU vs GPU) and propagates it across shuffle boundaries so that mapper-side and reducer-side stages can independently select the appropriate shuffle writer/reader and batch-resizing behavior.

Changes:

  • Add StageExecutionMode and propagate it through shuffle read paths (ShuffledColumnarBatchRDD, ColumnarShuffleManager, GlutenShuffleUtils).
  • Extend ColumnarShuffleExchangeExec to carry mapper/reducer stage modes and adjust shuffle writer selection accordingly.
  • Add AQE wrapper ColumnarAQEShuffleReadExec plus Velox rules (AdjustStageExecutionMode, updates to CudfNodeValidationRule) to set/propagate stage modes.

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
gluten-ut/spark41/src/test/scala/org/apache/spark/sql/GlutenPlanStabilitySuite.scala Update exchange matching to reflect ColumnarShuffleExchangeExec type.
gluten-ut/spark41/src/test/scala/org/apache/spark/sql/GlutenDataFrameWindowFunctionsSuite.scala Update pattern match for expanded ColumnarShuffleExchangeExec constructor.
gluten-ut/spark40/src/test/scala/org/apache/spark/sql/GlutenPlanStabilitySuite.scala Same as Spark 4.1 suite updates.
gluten-ut/spark40/src/test/scala/org/apache/spark/sql/GlutenDataFrameWindowFunctionsSuite.scala Same as Spark 4.1 suite updates.
gluten-ut/spark35/src/test/scala/org/apache/spark/sql/GlutenDataFrameWindowFunctionsSuite.scala Same pattern match update for Spark 3.5 suite.
gluten-ut/spark34/src/test/scala/org/apache/spark/sql/GlutenDataFrameWindowFunctionsSuite.scala Same pattern match update for Spark 3.4 suite.
gluten-ut/spark33/src/test/scala/org/apache/spark/sql/GlutenDataFrameWindowFunctionsSuite.scala Same pattern match update for Spark 3.3 suite.
gluten-substrait/src/main/scala/org/apache/spark/sql/execution/ShuffledColumnarBatchRDD.scala Add stage execution mode parameter; route to shuffle manager reader with mode.
gluten-substrait/src/main/scala/org/apache/spark/sql/execution/GPUColumnarShuffleExchangeExec.scala Removed legacy GPU-only shuffle exchange node.
gluten-substrait/src/main/scala/org/apache/spark/sql/execution/ColumnarShuffleExchangeExecBase.scala Removed base class; logic moved into ColumnarShuffleExchangeExec.
gluten-substrait/src/main/scala/org/apache/spark/sql/execution/ColumnarShuffleExchangeExec.scala Add mapper/reducer stage modes, node naming, and writer selection changes.
gluten-substrait/src/main/scala/org/apache/spark/sql/execution/adaptive/ColumnarAQEShuffleReadExec.scala New AQE shuffle-read wrapper that carries execution mode and forwards to columnar shuffle RDD.
gluten-substrait/src/main/scala/org/apache/spark/shuffle/sort/ColumnarShuffleManager.scala Add getReader(..., executionMode) overload and default CPU behavior.
gluten-substrait/src/main/scala/org/apache/spark/shuffle/GlutenShuffleUtils.scala Pass execution mode through shuffle reader generation; refactor codec validation.
gluten-substrait/src/main/scala/org/apache/spark/shuffle/GlutenShuffleReaderWrapper.scala Extend shuffle-reader parameter bundle with executionMode.
gluten-substrait/src/main/scala/org/apache/gluten/execution/StageExecutionMode.scala New execution-mode abstraction (CPU/GPU + testing mode).
gluten-substrait/src/main/scala/org/apache/gluten/execution/ColumnarCollectTailBaseExec.scala Update shuffle RDD construction for new ShuffledColumnarBatchRDD signature (currently hard-coded CPU).
gluten-substrait/src/main/scala/org/apache/gluten/execution/ColumnarCollectLimitBaseExec.scala Same as tail base exec; currently hard-coded CPU.
backends-velox/src/test/scala/org/apache/gluten/execution/MiscOperatorSuite.scala Adjust assertions to match new VeloxResizeBatchesExec configuration model.
backends-velox/src/main/scala/org/apache/spark/sql/execution/AdjustStageExecutionMode.scala New AQE rule to wrap shuffle reads / tag exchanges and resizers with stage execution mode.
backends-velox/src/main/scala/org/apache/gluten/extension/GpuBufferBatchResizeForShuffleInputOutput.scala Removed older rule in favor of stage-mode-driven resizing logic.
backends-velox/src/main/scala/org/apache/gluten/extension/CudfNodeValidationRule.scala Replace GPU-exchange construction with tagging + stage-mode propagation when AQE is off.
backends-velox/src/main/scala/org/apache/gluten/extension/AppendBatchResizeForShuffleInputAndOutput.scala Simplify resizer insertion now that VeloxResizeBatchesExec reads config internally.
backends-velox/src/main/scala/org/apache/gluten/execution/VeloxResizeBatchesExec.scala Switch resizer implementation based on stage execution mode (GPU vs CPU path).
backends-velox/src/main/scala/org/apache/gluten/backendsapi/velox/VeloxRuleApi.scala Wire in AdjustStageExecutionMode rule.
backends-velox/src/main/java/org/apache/gluten/utils/GpuBufferColumnarBatchResizer.java New JNI-backed GPU buffer batch resizer helper for GPU-stage resizing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +149 to +158
def getShuffleWriterType: ShuffleWriterType = {
mapperStageMode match {
case Some(GPUStageMode) =>
GpuHashShuffleWriterType
case _ =>
BackendsApiManager.getSparkPlanExecApiInstance.getShuffleWriterType(
outputPartitioning,
output)
}
}
Comment on lines 104 to 108
),
readMetrics
readMetrics,
// FIXME: pass proper StageExecutionMode
CPUStageMode
)
Comment on lines 103 to 107
),
readMetrics
readMetrics,
// FIXME: pass proper StageExecutionMode
CPUStageMode
)
case h: HashPartitioning =>
val partitions = partitionSpecs.map {
case CoalescedPartitionSpec(start, end, _) => CoalescedBoundary(start, end)
// Can not happend due to isCoalescedRead
Copilot AI review requested due to automatic review settings July 14, 2026 19:15
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@marin-ma marin-ma requested review from Copilot and removed request for Copilot July 14, 2026 19:16
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Copilot AI review requested due to automatic review settings July 15, 2026 09:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 195 out of 195 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (5)

gluten-substrait/src/main/scala/org/apache/gluten/execution/StageExecutionMode.scala:1

  • MockGPUStageMode uses the same id value as CPUStageMode (0). This makes StageExecutionMode.fromId(0) ambiguous and will always map back to CPUStageMode, so MockGPUStageMode can never round-trip correctly. Assign MockGPUStageMode a unique ID (or remove/move it to test scope if it's only intended for tests) and update fromId accordingly.
    gluten-substrait/src/main/scala/org/apache/spark/shuffle/sort/ColumnarShuffleManager.scala:1
  • The Spark ShuffleManager#getReader override unconditionally forces CPUStageMode. This contradicts the PR’s goal of allowing reducer stages to run in GPU mode and select a GPU shuffle reader when appropriate. Instead of hardcoding CPUStageMode, derive the execution mode from shuffle metadata (e.g., encode it in the shuffle handle/dependency) or from a task/stage property, and pass the derived value into the mode-aware overload.
    gluten-substrait/src/main/scala/org/apache/gluten/execution/ColumnarCollectLimitBaseExec.scala:1
  • Leaving a FIXME with a hardcoded CPUStageMode will likely reintroduce mode mismatches for collect-limit paths once GPU stages are enabled downstream. This should be resolved before merging by plumbing the correct StageExecutionMode into this call site (e.g., from the surrounding plan/stage context), or by redesigning the API so the mode is inferable without ad-hoc literals.
    gluten-substrait/src/main/scala/org/apache/gluten/execution/ColumnarCollectTailBaseExec.scala:1
  • Same issue as ColumnarCollectLimitBaseExec: hardcoding CPUStageMode with a FIXME makes stage-mode propagation incomplete and risks inconsistent shuffle reader/resizer selection. Please thread the actual StageExecutionMode through this path (mandatory if this code can run inside a GPU reducer stage).
    gluten-substrait/src/main/scala/org/apache/gluten/execution/StageExecutionMode.scala:1
  • Consider making StageExecutionMode a sealed trait to ensure exhaustive matching across the codebase (e.g., in fromId and other match sites). This is especially useful now that execution mode directly impacts shuffle reader/writer/resizer selection.

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@marin-ma marin-ma force-pushed the add-stage-execution-mode branch from 36f3ded to 2872874 Compare July 15, 2026 13:20
Copilot AI review requested due to automatic review settings July 15, 2026 13:20
@github-actions github-actions Bot removed the INFRA label Jul 15, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 196 out of 196 changed files in this pull request and generated 4 comments.

Comment on lines +24 to +40
case object CPUStageMode extends StageExecutionMode {
override def id: Int = 0
}
case object GPUStageMode extends StageExecutionMode {
override def id: Int = 1
}
case object MockGPUStageMode extends StageExecutionMode {
override def id: Int = 0
}

object StageExecutionMode {
def fromId(id: Int): StageExecutionMode = id match {
case 0 => CPUStageMode
case 1 => GPUStageMode
case _ => throw new IllegalArgumentException(s"Unknown StageExecutionMode id: $id")
}
}
Comment on lines 94 to 108
new ShuffledColumnarBatchRDD(
BackendsApiManager.getSparkPlanExecApiInstance.genShuffleDependency(
locallyLimited,
child.output,
child.output,
SinglePartition,
serializer,
writeMetrics,
metrics,
shuffleWriterType
),
readMetrics
readMetrics,
// FIXME: pass proper StageExecutionMode
CPUStageMode
)
Comment on lines 154 to 178
def genColumnarShuffleReader[K, C](
handle: ShuffleHandle,
startMapIndex: Int,
endMapIndex: Int,
startPartition: Int,
endPartition: Int,
context: TaskContext,
metrics: ShuffleReadMetricsReporter): ShuffleReader[K, C] = {
metrics: ShuffleReadMetricsReporter,
executionMode: StageExecutionMode): ShuffleReader[K, C] = {
val (blocksByAddress, canEnableBatchFetch) = {
getReaderParam(handle, startMapIndex, endMapIndex, startPartition, endPartition)
}
val shouldBatchFetch =
canEnableBatchFetch && canUseBatchFetch(startPartition, endPartition, context)

BackendsApiManager.getSparkPlanExecApiInstance
.genColumnarShuffleReader(
GenShuffleReaderParameters(
handle.asInstanceOf[BaseShuffleHandle[K, _, C]],
blocksByAddress,
context,
metrics,
shouldBatchFetch))
shouldBatchFetch,
executionMode))
.shuffleReader
Comment on lines 93 to 107
new ShuffledColumnarBatchRDD(
BackendsApiManager.getSparkPlanExecApiInstance.genShuffleDependency(
locallyLimited,
child.output,
child.output,
SinglePartition,
serializer,
writeMetrics,
metrics,
shuffleWriterType
),
readMetrics
readMetrics,
// FIXME: pass proper StageExecutionMode
CPUStageMode
)
Copilot AI review requested due to automatic review settings July 15, 2026 13:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 196 out of 196 changed files in this pull request and generated 3 comments.

Comment on lines +30 to +40
case object MockGPUStageMode extends StageExecutionMode {
override def id: Int = 0
}

object StageExecutionMode {
def fromId(id: Int): StageExecutionMode = id match {
case 0 => CPUStageMode
case 1 => GPUStageMode
case _ => throw new IllegalArgumentException(s"Unknown StageExecutionMode id: $id")
}
}
Comment on lines 104 to 108
),
readMetrics
readMetrics,
// FIXME: pass proper StageExecutionMode
CPUStageMode
)
Comment on lines 103 to 107
),
readMetrics
readMetrics,
// FIXME: pass proper StageExecutionMode
CPUStageMode
)
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@marin-ma marin-ma force-pushed the add-stage-execution-mode branch from 6a5ae36 to 98974fc Compare July 15, 2026 17:23
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

2 similar comments
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CORE works for Gluten Core VELOX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants