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]

Reply via email to