wbo4958 commented on code in PR #44690:
URL: https://github.com/apache/spark/pull/44690#discussion_r1477679566


##########
core/src/main/scala/org/apache/spark/resource/ResourceAllocator.scala:
##########
@@ -20,6 +20,49 @@ package org.apache.spark.resource
 import scala.collection.mutable
 
 import org.apache.spark.SparkException
+import org.apache.spark.resource.ResourceAmountUtils.ONE_ENTIRE_RESOURCE
+
+private[spark] object ResourceAmountUtils {
+  /**
+   * Using "double" to do the resource calculation may encounter a problem of 
precision loss. Eg
+   *
+   * scala> val taskAmount = 1.0 / 9
+   * taskAmount: Double = 0.1111111111111111
+   *
+   * scala> var total = 1.0
+   * total: Double = 1.0
+   *
+   * scala> for (i <- 1 to 9 ) {
+   * |   if (total >= taskAmount) {
+   * |           total -= taskAmount
+   * |           println(s"assign $taskAmount for task $i, total left: $total")
+   * |   } else {
+   * |           println(s"ERROR Can't assign $taskAmount for task $i, total 
left: $total")
+   * |   }
+   * | }
+   * assign 0.1111111111111111 for task 1, total left: 0.8888888888888888
+   * assign 0.1111111111111111 for task 2, total left: 0.7777777777777777
+   * assign 0.1111111111111111 for task 3, total left: 0.6666666666666665
+   * assign 0.1111111111111111 for task 4, total left: 0.5555555555555554
+   * assign 0.1111111111111111 for task 5, total left: 0.44444444444444425
+   * assign 0.1111111111111111 for task 6, total left: 0.33333333333333315
+   * assign 0.1111111111111111 for task 7, total left: 0.22222222222222204
+   * assign 0.1111111111111111 for task 8, total left: 0.11111111111111094
+   * ERROR Can't assign 0.1111111111111111 for task 9, total left: 
0.11111111111111094
+   *
+   * So we multiply ONE_ENTIRE_RESOURCE to convert the double to long to avoid 
this limitation.
+   * Double can display up to 16 decimal places, so we set the factor to
+   * 10, 000, 000, 000, 000, 000L.
+   */
+  final val ONE_ENTIRE_RESOURCE: Long = 10000000000000000L

Review Comment:
   Hi @srowen, Yeah, as long as we use double to do the calculation, we can't 
avoid the precision issue. We can also check the absolute value of the 
difference between two numbers, But it seems it doesn't make any difference?
   
   
   ``` scala
   scala> val taskAmount = 0.05
   taskAmount: Double = 0.05
   
   scala> var total = 1.0
   total: Double = 1.0
   
   scala> for (i <- 1 to 20 ) {
        |   if (total >= taskAmount) {
        |              total -= taskAmount
        |              println(s"assign $taskAmount for task $i, total left: 
$total")
        |      } else {
        |              println(s"ERROR Can't assign $taskAmount for task $i, 
total left: $total")
        |      }
        | }
   assign 0.05 for task 1, total left: 0.95
   assign 0.05 for task 2, total left: 0.8999999999999999
   assign 0.05 for task 3, total left: 0.8499999999999999
   assign 0.05 for task 4, total left: 0.7999999999999998
   assign 0.05 for task 5, total left: 0.7499999999999998
   assign 0.05 for task 6, total left: 0.6999999999999997
   assign 0.05 for task 7, total left: 0.6499999999999997
   assign 0.05 for task 8, total left: 0.5999999999999996
   assign 0.05 for task 9, total left: 0.5499999999999996
   assign 0.05 for task 10, total left: 0.4999999999999996
   assign 0.05 for task 11, total left: 0.4499999999999996
   assign 0.05 for task 12, total left: 0.39999999999999963
   assign 0.05 for task 13, total left: 0.34999999999999964
   assign 0.05 for task 14, total left: 0.29999999999999966
   assign 0.05 for task 15, total left: 0.24999999999999967
   assign 0.05 for task 16, total left: 0.19999999999999968
   assign 0.05 for task 17, total left: 0.1499999999999997
   assign 0.05 for task 18, total left: 0.09999999999999969
   assign 0.05 for task 19, total left: 0.049999999999999684
   ERROR Can't assign 0.05 for task 20, total left: 0.049999999999999684
   ```
   
   Take the above code as an example, taskAmount=0.05, which I think is a very 
normal value, but we can't assign the resources to a total of 20 tasks due to 
precision issues. 
   
   If we convert double to Long, it can work
   
   ``` scala
   scala> val ONE_ENTIRE_RESOURCE: Long = 10000000000000000L
   ONE_ENTIRE_RESOURCE: Long = 10000000000000000
   
   scala> 
   
   scala> val taskAmount = 0.05
   taskAmount: Double = 0.05
   
   scala> var total = 1.0 * ONE_ENTIRE_RESOURCE
   total: Double = 1.0E16
   
   scala> for (i <- 1 to 20 ) {
        |   if (total >= taskAmount * ONE_ENTIRE_RESOURCE) {
        |              total -= taskAmount * ONE_ENTIRE_RESOURCE
        |              println(s"assign $taskAmount for task $i, total left: 
$total")
        |      } else {
        |              println(s"ERROR Can't assign $taskAmount for task $i, 
total left: $total")
        |      }
        | }
   assign 0.05 for task 1, total left: 9.5E15
   assign 0.05 for task 2, total left: 9.0E15
   assign 0.05 for task 3, total left: 8.5E15
   assign 0.05 for task 4, total left: 8.0E15
   assign 0.05 for task 5, total left: 7.5E15
   assign 0.05 for task 6, total left: 7.0E15
   assign 0.05 for task 7, total left: 6.5E15
   assign 0.05 for task 8, total left: 6.0E15
   assign 0.05 for task 9, total left: 5.5E15
   assign 0.05 for task 10, total left: 5.0E15
   assign 0.05 for task 11, total left: 4.5E15
   assign 0.05 for task 12, total left: 4.0E15
   assign 0.05 for task 13, total left: 3.5E15
   assign 0.05 for task 14, total left: 3.0E15
   assign 0.05 for task 15, total left: 2.5E15
   assign 0.05 for task 16, total left: 2.0E15
   assign 0.05 for task 17, total left: 1.5E15
   assign 0.05 for task 18, total left: 1.0E15
   assign 0.05 for task 19, total left: 5.0E14
   assign 0.05 for task 20, total left: 0.0
   ```



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