sunchao commented on code in PR #56516:
URL: https://github.com/apache/spark/pull/56516#discussion_r3816903008
##########
core/src/main/scala/org/apache/spark/scheduler/DAGScheduler.scala:
##########
@@ -853,17 +853,10 @@ private[spark] class DAGScheduler(
val startResourceProfile = stageResourceProfiles.head
val mergedProfile = stageResourceProfiles.drop(1)
.foldLeft(startResourceProfile)((a, b) => mergeResourceProfiles(a,
b))
- // compared merged profile with existing ones so we don't add it over
and over again
- // if the user runs the same operation multiple times
- val resProfile =
sc.resourceProfileManager.getEquivalentProfile(mergedProfile)
- resProfile match {
- case Some(existingRp) => existingRp
- case None =>
- // this ResourceProfile could be different if it was merged so we
have to add it to
- // our ResourceProfileManager
- sc.resourceProfileManager.addResourceProfile(mergedProfile)
- mergedProfile
- }
+ // compare the merged profile with existing ones so we don't add it
over and over again
+ // if the user runs the same operation multiple times. The merged
ResourceProfile could
+ // be different from any existing one, in which case it is registered
here.
+ sc.resourceProfileManager.getOrAddEquivalentProfile(mergedProfile)
Review Comment:
[P2] Preserve valid default/task-only merges with static allocation
With dynamic allocation disabled and
`spark.scheduler.resource.profileMergeConflicts=true`, a stage can combine the
actual default profile with a task-only profile that adds no requirements. The
actual default object is publicly obtainable from
`SparkListenerResourceProfileAdded` through a listener registered in
`spark.extraListeners`; both `withResources` calls below are accepted on a
static Standalone/YARN/Kubernetes application:
```scala
// capturedDefault is the ID-0 object received by the listener.
// Application spark.task.cpus is 1.
val taskOnly = new ResourceProfileBuilder()
.require(new TaskResourceRequests().cpus(1))
.build()
val rdd = sc.parallelize(1 to 10, 2)
.withResources(capturedDefault)
.map(x => x)
.withResources(taskOnly)
```
At the base, merging these profiles produces the default's resource maps and
`getEquivalentProfile` returns the already-registered ID 0. This new call
instead runs `isSupported` on the freshly constructed, nonzero-ID full profile
and throws the dynamic-allocation support error. An action on this otherwise
valid RDD therefore fails during stage creation, even though it needs only the
existing default executors.
I verified this with the same local-cluster regression test on both commits:
base `4e0b430619e67bf3880a9ecaed103df5eea0e531` passes; head
`29d353ce49b3f25406c9372e2bcc4403f4a62337` fails at this line through
`ResourceProfileManager.scala:142`.
Could we preserve the actual default when a task-only merge adds no
requirements, while still keeping independently supplied explicit executor
profiles distinct, and add a static-allocation regression test?
--
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]