marin-ma commented on code in PR #12511:
URL: https://github.com/apache/gluten/pull/12511#discussion_r3602190627


##########
gluten-substrait/src/main/scala/org/apache/spark/sql/execution/ColumnarShuffleExchangeExec.scala:
##########
@@ -16,29 +16,217 @@
  */
 package org.apache.spark.sql.execution
 
+import org.apache.gluten.backendsapi.BackendsApiManager
+import org.apache.gluten.config.{GpuHashShuffleWriterType, ShuffleWriterType}
+import org.apache.gluten.execution.{CPUStageMode, GPUStageMode, 
StageExecutionMode, ValidatablePlan, ValidationResult}
+import org.apache.gluten.extension.columnar.transition.Convention
 import org.apache.gluten.sql.shims.SparkShimLoader
 
+import org.apache.spark._
 import org.apache.spark.internal.Logging
+import org.apache.spark.rdd.RDD
+import org.apache.spark.serializer.Serializer
+import org.apache.spark.sql.catalyst.InternalRow
 import org.apache.spark.sql.catalyst.expressions.Attribute
-import org.apache.spark.sql.catalyst.plans.physical._
+import org.apache.spark.sql.catalyst.plans.logical.Statistics
+import org.apache.spark.sql.catalyst.plans.physical.{SinglePartition, _}
+import org.apache.spark.sql.catalyst.util.truncatedString
 import org.apache.spark.sql.execution.exchange._
+import org.apache.spark.sql.execution.metric.SQLShuffleWriteMetricsReporter
+import org.apache.spark.sql.metric.SQLColumnarShuffleReadMetricsReporter
+import org.apache.spark.sql.vectorized.ColumnarBatch
+
+import scala.concurrent.Future
 
 case class ColumnarShuffleExchangeExec(
     override val outputPartitioning: Partitioning,
     child: SparkPlan,
     shuffleOrigin: ShuffleOrigin = ENSURE_REQUIREMENTS,
     projectOutputAttributes: Seq[Attribute],
-    advisoryPartitionSize: Option[Long] = None)
-  extends ColumnarShuffleExchangeExecBase(outputPartitioning, child, 
projectOutputAttributes) {
+    advisoryPartitionSize: Option[Long] = None,
+    mapperStageMode: Option[StageExecutionMode] = None,
+    reducerStageMode: Option[StageExecutionMode] = None)
+  extends ShuffleExchangeLike
+  with ValidatablePlan {
+
+  override def nodeName: String = "ColumnarShuffleExchange" + {
+    if (mapperStageMode.isDefined) {
+      if (conf.adaptiveExecutionEnabled) {
+        // In AQE, the reducer stage mode is set in the downstream query stage.
+        // It is shown in the ColumnarAQEShuffleReaderExec node.
+        s"(${mapperStageMode.get.name})"
+      } else {
+        // Mapper and reducer stage modes should be set together when AQE is 
disabled.
+        if (reducerStageMode.isEmpty) {
+          throw new IllegalStateException(
+            "Reducer stage mode is not defined in ColumnarShuffleExchangeExec 
when AQE is disabled")
+        }
+        s"(${mapperStageMode.get.name}, ${reducerStageMode.get.name})"
+      }
+    } else {
+      ""
+    }
+  }
+
+  private[sql] lazy val writeMetrics =
+    SQLShuffleWriteMetricsReporter.createShuffleWriteMetrics(sparkContext)
+
+  private[sql] lazy val readMetrics =
+    
SQLColumnarShuffleReadMetricsReporter.createShuffleReadMetrics(sparkContext)
+
+  lazy val shuffleWriterType: ShuffleWriterType = getShuffleWriterType
+
+  // super.stringArgs ++ Iterator(output.map(o => 
s"${o}#${o.dataType.simpleString}"))
+  lazy val serializer: Serializer = 
BackendsApiManager.getSparkPlanExecApiInstance
+    .createColumnarBatchSerializer(schema, metrics, shuffleWriterType)
+
+  // Note: "metrics" is made transient to avoid sending driver-side metrics to 
tasks.
+  @transient override lazy val metrics =
+    BackendsApiManager.getMetricsApiInstance
+      .genColumnarShuffleExchangeMetrics(
+        sparkContext,
+        shuffleWriterType) ++ readMetrics ++ writeMetrics
+
+  @transient lazy val inputColumnarRDD: RDD[ColumnarBatch] = 
child.executeColumnar()
+
+  // 'mapOutputStatisticsFuture' is only needed when enable AQE.
+  @transient override lazy val mapOutputStatisticsFuture: 
Future[MapOutputStatistics] = {
+    if (inputColumnarRDD.getNumPartitions == 0) {
+      Future.successful(null)
+    } else {
+      sparkContext.submitMapStage(columnarShuffleDependency)
+    }
+  }
 
-  override def nodeName: String = "ColumnarExchange"
+  /**
+   * A [[ShuffleDependency]] that will partition rows of its child based on 
the partitioning scheme
+   * defined in `newPartitioning`. Those partitions of the returned 
ShuffleDependency will be the
+   * input of shuffle.
+   */
+  @transient
+  lazy val columnarShuffleDependency: ShuffleDependency[Int, ColumnarBatch, 
ColumnarBatch] = {
+    BackendsApiManager.getSparkPlanExecApiInstance.genShuffleDependency(
+      inputColumnarRDD,
+      child.output,
+      projectOutputAttributes,
+      outputPartitioning,
+      serializer,
+      writeMetrics,
+      metrics,
+      shuffleWriterType)
+  }
+
+  var cachedShuffleRDD: ShuffledColumnarBatchRDD = _
+
+  override protected def doValidateInternal(): ValidationResult = {
+    val validation = BackendsApiManager.getValidatorApiInstance
+      .doColumnarShuffleExchangeExecValidate(output, outputPartitioning, child)
+    if (validation.nonEmpty) {
+      return ValidationResult.failed(
+        s"Found schema check failure for schema ${child.schema} due to: 
${validation.get}")
+    }
+    outputPartitioning match {
+      case _: HashPartitioning => ValidationResult.succeeded
+      case _: RangePartitioning => ValidationResult.succeeded
+      case SinglePartition => ValidationResult.succeeded
+      case _: RoundRobinPartitioning => ValidationResult.succeeded
+      case _ =>
+        ValidationResult.failed(
+          s"Unsupported partitioning 
${outputPartitioning.getClass.getSimpleName}")
+    }
+  }
+
+  override def numMappers: Int = inputColumnarRDD.getNumPartitions
+
+  override def numPartitions: Int = 
columnarShuffleDependency.partitioner.numPartitions
+
+  override def runtimeStatistics: Statistics = {
+    val dataSize = metrics("dataSize").value
+    val rowCount = 
metrics(SQLShuffleWriteMetricsReporter.SHUFFLE_RECORDS_WRITTEN).value
+    Statistics(dataSize, Some(rowCount))
+  }
+
+  def getShuffleWriterType: ShuffleWriterType = {
+    mapperStageMode match {
+      case Some(GPUStageMode) =>
+        GpuHashShuffleWriterType
+      case _ =>
+        BackendsApiManager.getSparkPlanExecApiInstance.getShuffleWriterType(
+          outputPartitioning,
+          output)
+    }
+  }

Review Comment:
   `GpuHashShuffleWriterType` no longer represents a shuffle writer type and 
should be removed. Will do the cleanup in the following pr.



-- 
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