Fix Spark master GpuBatchScanExec compile after replanWithRuntimeFilters API change[reduced-it] - #15932
Conversation
Spark master now takes Option[KeyedPartitioning] and requires the full-width reported keys, not the possibly projected outputPartitioning. Signed-off-by: Firestarman <firestarmanllc@gmail.com>
|
Ignore pruned-out partition keys in equals/hashCode and canonicalize with normalizeExpressions so key order is preserved (SPARK-58120). Signed-off-by: Firestarman <firestarmanllc@gmail.com>
|
build |
| outputPartitioning, | ||
| // Full-width keys as the source reported them. outputPartitioning may project | ||
| // pruned key columns away and is a Partitioning, not Option[KeyedPartitioning]. | ||
| reportedKeyedPartitioning, |
There was a problem hiding this comment.
[P1] Could we add an end-to-end regression test for the full-width key behavior exercised here? The new suite never evaluates filteredPartitions, and the existing Iceberg DPP case uses a single, unpruned partition key. An implementation that passes None or the pruned keys here would therefore still pass the current tests, while a runtime-filter replan after pruning a leading key can misalign keyed partitions, return wrong rows, or throw ClassCastException. Please port the SPARK-59248-style query with a multi-column key, a pruned leading key, and a runtime filter, and assert CPU/GPU result equality plus the GPU scan/SPJ plan.
There was a problem hiding this comment.
Added a Spark 5 suite case that actually evaluates filteredPartitions. It uses a keyed GpuScan whose partitions implement HasPartitionKey with (store_id, dept_id), prunes the leading store_id from scan output, and applies a runtime filter on dept_id (SPARK-59248 shape). The test asserts padded None slots, remaining keys still two fields wide, and only dept_id=10 kept.
Spark 5 unit tests compile against the Iceberg stub, so this is not an Iceberg SQL IT. Passing None or the pruned one-column planner keys here fails the keyed replan (misaligned HasPartitionKey rows) rather than staying green.
| keyGroupedPartitioning = keys) | ||
| } | ||
|
|
||
| test("equals and hashCode ignore partition keys pruned out of output") { |
There was a problem hiding this comment.
[P2] Could this be covered through Spark's actual plan-comparison path? These assertions call equals, hashCode, and doCanonicalize directly, so they do not verify the AQE reuse / sameResult behavior claimed in the PR description. Please add a query that produces semantically equivalent scans with different ExprIds and assert sameResult or ReusedExchangeExec; that would catch integration issues between canonicalization and physical-plan reuse.
There was a problem hiding this comment.
The dangling-key case now also asserts sameResult, which goes through SparkPlan.canonicalized (the path AQE reuse uses). There is a second test that builds two GpuBatchScanExecs that differ only by ExprId and asserts sameResult between them.
A ReusedExchangeExec SQL query is not added here: Spark 5 UTs do not have a GPU DSv2 source that reports HasPartitionKey (parquet file partitions do not implement it; Iceberg is stubbed). sameResult on the GPU scan nodes is what would decide reuse for those plans.
| import org.apache.spark.sql.connector.read.{Batch, InputPartition, PartitionReaderFactory} | ||
| import org.apache.spark.sql.types.{IntegerType, StringType, StructType} | ||
|
|
||
| class GpuBatchScanExecCanonicalizeSuite extends SparkQueryCompareTestSuite with MockitoSugar { |
There was a problem hiding this comment.
[P2] PR description issue (anchored here because it describes validation for this suite): mvn ... validate stops before compile and test, so the listed command does not support "Compile was checked." Please replace it with an actual compile, package, install, or test command and its result. For example, a Spark 5 / Scala 2.13 reactor install followed by this targeted suite would substantiate both compilation and test coverage.
There was a problem hiding this comment.
Updated the PR description. Compile and this suite were checked with:
mvn -f scala2.13/pom.xml -Dbuildver=500 -Dcuda.version=cuda13 -pl sql-plugin,tests -am package -DwildcardSuites=com.nvidia.spark.rapids.shims.GpuBatchScanExecCanonicalizeSuite
That package run compiled sql-plugin + tests and reported BUILD SUCCESS with 4 tests in GpuBatchScanExecCanonicalizeSuite.
Evaluate filteredPartitions after a pruned leading key plus runtime filter, and assert sameResult through SparkPlan canonicalization. Signed-off-by: Firestarman <firestarmanllc@gmail.com>
Signed-off-by: Firestarman <firestarmanllc@gmail.com>
|
build |
|
build |
Fixes #15930.
Description
Spark master nightly builds fail in
sql-pluginwhile compiling the Spark 5.0 shim:GpuBatchScanExecstill passesoutputPartitioning(Partitioning) intoPushDownUtils.replanWithRuntimeFilters, which now takesOption[KeyedPartitioning]. Released Spark versions are unaffected. After this change, Spark 5 / master snapshot compilation succeeds again. No new configuration.The helper must use the full-width keys the source reported, not the planner view.
outputPartitioningmay project away pruned key columns and is the wrong type. GPUGpuBatchScanExecnow passesreportedKeyedPartitioningfromDataSourceV2ScanExecBase, matching Spark'sBatchScanExec.The same Spark 5
BatchScanExecalso treats pruned-out partition keys as planner metadata:equals,hashCode, anddoCanonicalizeuseprunedKeyGroupedPartitioning, and canonicalize usesnormalizeExpressionsso multi-key order is preserved (SPARK-58120). Those were ported as well so GPU AQE reuse /sameResultdoes not diverge from CPU, and so a canonicalized keyed scan cannot reorder Integer/String keys.Compile and the Spark 5 suite were checked with
mvn -f scala2.13/pom.xml -Dbuildver=500 -Dcuda.version=cuda13 -pl sql-plugin,tests -am package -DwildcardSuites=com.nvidia.spark.rapids.shims.GpuBatchScanExecCanonicalizeSuite(BUILD SUCCESS, 4 tests).GpuBatchScanExecCanonicalizeSuitecovers dangling-key equality,sameResultacross differentExprIds, SPARK-58120 key order, and SPARK-59248-style runtime-filter replanning after a pruned leading key (filteredPartitionson a keyedGpuScan). Spark 5 unit tests use the Iceberg stub, so that last case is aGpuScanwithHasPartitionKeypartitions rather than an Iceberg query. Existing Spark 4 Iceberg SPJ / DSv2 scan tests still cover the Iceberg runtime-filter path.This change was drafted with AI assistance. A human reviewed the diff and this description before updating the PR.
Checklists
Documentation
Testing
Performance
Driver-side plan identity and a compile-time argument swap when building scan partitions. No per-row or executor GPU work is added.
reportedKeyedPartitioningis already the lazy valueoutputPartitioningis derived from in Spark'sDataSourceV2ScanExecBase.